管道是Linux中进程间通信的一种方式,它把一个程序的输出直接连接到另一个程序的输入。
无名管道
1.它只能用于具有亲缘关系的进程间通信(父子进程或兄弟进程之间)
2.是一个半双工的通信模式,具有固定的读端和写端
半双工:指数据可以沿着两个方向传输,但同一时刻一个信道只能允许单方向传送,又称为双向交替通信。
3.可以看作一种特殊的文件,可以使用普通的read()、write()等函数。但它不是普通的文件,并不属于其他任何文件系统且只存在于内存中。
图例
示例
#include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { int pipefd[2]; int pid; if (pipe(pipefd) < 0){ return -1; } pid = fork(); if (pid < 0 ){ return -1; }else if (pid == 0){ //关闭写入端,从管道读取数据 close(pipefd[1]); //将管道读取端重定向到0 dup2(pipefd[0], 0); execl("/usr/bin/wc", "wc", NULL); } //关闭管道读取端,写入数据 close(pipefd[0]); //将管道重定向至1 dup2(pipefd[1], 1); close(pipefd[1]); execl("/bin/ls", "ls","-l", NULL); close(1); return 0; }
1.使用pipe创建无名管道
2.子进程关闭写端,从fd[0]读取数据
3.父进程关闭读端,从fd[1]写入数据
4.父进程执行ls, 将结果交给子进程执行wc命令,将最终结果打印出来
命名管道
1.可以使互不相关的连个进程间实现彼此通信
2.该管道可以通过路径名指出,且在文件系统中是可见的。在建立管道之后,两个进程可以把它当做普通文件一样进行读写操作,使用更加方便
3.FIFO严格遵循先进先出规则,对管道及FIFO的读总是从开始处返回数据,写则把数据添加到末尾,不支持如lseek()等文件定位操作。
图例
示例
#include <stdio.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> void test() { printf("test\n"); } int main(int argc, char *argv[]) { int fifofd; char buff[1024]; umask(0); if (mkfifo("./test.fifo", 0664) < 0){ if (errno != EEXIST){ return -1; } } fifofd = open("./test.fifo", O_RDWR); if (fifofd < 0){ return -1; } while (1){ memset(buff, 0x00, 1024); read(fifofd, buff, 1024); if (strncasecmp(buff, "test", 4) == 0){ test(); } } close(fifofd); return 0; }
1.mkfifo创建管道
2.使用open打开管道文件
3.开始对管道文件进行读写操作
4.通过外部向管道文件写入数据,来实现在程序内部调用test函数,实现指定功能