linux C 管道
单一进程使用管道基本上毫无意义。管道一般用来子进程和父进程之间的通信,或者兄弟进程间的通信。
创建管道的主要函数是pipe
#include<unistd.h> int pipe (int filedes[2])
pipe函数创建一个管道,为管道的两端设置文件描述符。我们通过文件描述符进行读写。写入端的文件描述符存放在filedes[0]中,读出端则在filedes[1]中。(在linux中文件描述符0为标准输入,1为标准输出)
成功返回0,失败返回-1(并设置errno)
#include<sys/types.h> #include<unistd.h> #include<stdio.h> #include<stdlib.h> //定义两个管道读写函数 void read_pipe (int file) { FILE *stream; int c; stream = fdopen (file, "r"); while ((c = fgetc (stream)) != EOF) putchar (c); fclose (stream); } void write_pipe (int file) { FILE *stream; stream = fdopen (file, "w"); fptintf (stream, "hello, world!\n"); fprintf (stream, "goodbye, world!\n"); fclose (stream); } int main (void) { pid_t pid; int filedes[2]; //创建管道 if (pipe (mypipe)) { fprintf(stderr, "Pipe failed. \n"); return EXIT_FAILURE; } //创建子进程 pid = fork(); if (pid == (pid_t)0) {//子进程开始读管道,读的时候需要先关闭输入端口 close (filedes[1]); read_pipe(filedes[0]); return EXIT_SUCCESS; } else if (pid < (pid_t) 0) {//fork失败, fprintf (stderr, "Fork failed.\n"); return EXIT_FAILURE; } else {//父进程开始写管道,先关闭读出端; close (filedes[0]); write_pipe(filedes[1]); return EXIT_SUCCESS; } }
还有一种关于匿名管道的函数popen,同样是传递消息给子进程的,不同的是子进程是command参数指定linux 命令(可执行程序, 由exec执行)
#include <stdio.h> FILE *popen (const char *command, const char *mode)
mode参数指定了管道的模式,可以是"r" (以读的方式打开管道)、"w"(以写的方式打开管道)。和文件读写一样。
与之配套的函数pclose用来关闭管道
#include <stdio.h>
int pclose (FILE *stream)
简单代码示例
#include<stdio.h> int main() { FILE *output = popen ("more", "w"); for (i = 0; i < 100; i++) fprintf(output, "received form main process %d\n", i); pclose (output); }
以上管道都是匿名的(只能在子进程和父进程,或者兄弟进程之间使用)。我们可以给管道起个名字,这样任意有权限的进程都可以使用。这样的管道被称为FIFO Special Files。但是FIFO的两端的进程读写必须同时就位后,才可以传送消息。否则其中一端会被阻塞(可以设置一个缓冲区,用来接收写入的消息,这样就可以异步通信了)
#include<sys/stat.h> int mkfifo (const char *filename, mode_t mode)
filename参数用来设置FIFO名字,mode用来设置读写权限。
在管道中传输的数据如果比较大,会分次传输。