C语言 管道

mac2025-10-15  6

管道

================================================================== pipe (建立管道)

头文件:

#include <unistd.h>

定义函数:

int pipe(int filedes[2]);

函数说明 :

pipe()会建立管道, 并将文件描述词由参数 filedes 数组返回. filedes[0]为管道里的读取端, filedes[1]则为管道的写入端.

返回值:

若成功则返回零, 否则返回-1, 错误原因存于 errno 中. 错误代码 EMFILE 进程已用完文件描述词最大量. ENFILE 系统已无文件描述词可用. EFAULT 参数 filedes 数组地址不合法.

DEMO:

#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <errno.h> //函数声明 void func(void); int main(int argc, char const *argv[]) { //创建一个无名管道 filedes[0]读取端 filedes[1]写入端 int filedes[2]; int ret = pipe(filedes); if(-1 == ret) { perror("pipe error\n"); return -1; } //创建一个子进程 pid_t x = fork(); //子进程 if(x == 0) { printf("[%d]this is child process\n", (int)getpid()); //往无名管道写入端写 char *buf = malloc(25); printf("child:"); //从键盘输入 bzero(buf, 25); fgets(buf, 25, stdin); write(filedes[1], buf, strlen(buf)); } //父进程 if(x > 0) { printf("[%d]this is father process\n", (int)getpid()); //等待子进程退出 wait(NULL); //从无名管道读取端读 char *buf = malloc(25); bzero(buf, 25); read(filedes[0], buf, 25); printf("[%d]从无名管道子进程中读到的内容:%s", (int)getpid(), buf); } ret = atexit(func); if(-1 == ret) { perror("atexit error\n"); } #ifdef _EXIT _exit(0); //直接退出 #else exit(0); //正常退出 #endif } void func(void) { printf("[%d]eixt succeed\n", (int)getpid()); }

================================================================== mkfifo ( 建立具名管道 )

头文件: #include <sys/types.h> #include <sys/stat.h>

定义函数 :

int mkfifo(const char * pathname, mode_t mode);

函数说明 :

mkfifo()会依参数 pathname 建立特殊的 FIFO 文件, 该文件必须不存在, 而参数 mode 为该文件的权限 (mode%~umask), 因此 umask 值也会影响到 FIFO 文件的权限. Mkfifo()建立的 FIFO 文件其他进程都可以用读写一般文件的方式存取. 当使用 open()来打开 FIFO 文件时, O_NONBLOCK 旗标会有影响 当使用 O_NONBLOCK 旗标时, 打开 FIFO 文件来读取的操作会立刻返回, 但是若还没有其他进 程打开 FIFO 文件来读取, 则写入的操作会返回 ENXIO 错误代码.没有使用 O_NONBLOCK 旗标时, 打开 FIFO 来读取的操作会等到其他进程打开 FIFO 文件来写入才正常返回. 同样地, 打开 FIFO 文件来写入的操作会等到其他进程打开 FIFO 文件来读取后才正常返回.

返回值 :

若成功则返回 0, 否则返回-1, 错误原因存于 errno 中. 错误代码 EACCESS 参数 pathname 所指定的目录路径无可执行的权限 EEXIST 参数 pathname 所指定的文件已存在. ENAMETOOLONG 参数 pathname 的路径名称太长. ENOENT 参数 pathname 包含的目录不存在 ENOSPC 文件系统的剩余空间不足 ENOTDIR 参数 pathname 路径中的目录存在但却非真正的目录. EROFS 参数 pathname 指定的文件存在于只读文件系统内.

================================================================== access ( 判断是否具有存取文件的权限 )

头文件 : #include <unistd.h>

定义函数 :

int access(const char * pathname, int mode);

函数说明 :

access()会检查是否可以读/写某一已存在的文件. 参数 mode 有几种情况组合, R_OK, W_OK, X_OK和 F_OK. R_OK, W_OK 与 X_OK 用来检查文件是否具有读娶写入和执行的权限. F_OK 则是用来判断该文件是否存在. 由于 access()只作权限的核查, 并不理会文件形态或文件内容, 因此, 如果一目录表示为"可写入", 表示可以在该目录中建立新文件等操作, 而非意味此目录可以被当做文件处理. 例如, 你会发现 DOS 的文件都具有"可执行"权限, 但用 execve()执行时则会失败.

返回值:

若所有欲查核的权限都通过了检查则返回 0 值, 表示成功, 只要有一权限被禁止则返回-1.

以下两个demo都得运行 DEMO1:

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <stdlib.h> #include <errno.h> #define FIFO_PATH "/tmp/xxno/mkfifo" #define BUF_SIZE 30 int main(int argc, char const *argv[]) { //创建有名管道文件: if(access(FIFO_PATH, F_OK | W_OK)) { int ret = mkfifo(FIFO_PATH, 0666); if(-1 == ret) { perror("mkfifo error\n"); return -1; } } //打开管道文件: int fd_fifo = open(FIFO_PATH, O_WRONLY); if(-1 == fd_fifo) { perror("open error\n"); return -1; } while(1) { //往管道文件里写内容: char *buf = malloc(BUF_SIZE); printf("写入管道中:\n"); fgets(buf, BUF_SIZE, stdin); write(fd_fifo, buf, strlen(buf)); } //关闭管道文件: close(fd_fifo); return 0 ; }

DEMO2:

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <stdlib.h> #include <errno.h> #define FIFO_PATH "/tmp/xxno/mkfifo" #define BUF_SIZE 30 int main(int argc, char const *argv[]) { //创建有名管道文件: if(access(FIFO_PATH, F_OK | R_OK)) { int ret = mkfifo(FIFO_PATH, 0666); if(-1 == ret) { perror("mkfifo error\n"); return -1; } } //打开管道文件: int fd_fifo = open(FIFO_PATH, O_RDONLY); if(-1 == fd_fifo) { perror("open error\n"); return -1; } //往管道文件里写内容: while(1) { char *buf = malloc(BUF_SIZE); int ret = read(fd_fifo, buf, BUF_SIZE); if(0 == ret) { break; } printf("%s\n", buf); } //关闭管道文件: close(fd_fifo); return 0 ; }
最新回复(0)