进程间通信——管道

来源:互联网 发布:js 三个等号 编辑:程序博客网 时间:2024/05/21 13:28

用管道来进行进程间通信是通过pipe函数,管道只能支持父子进程或有公共祖先的进程之间通信。

pipe函数原型:

#include <unistd.h>int pipe (int fd[2]);
该函数被调用后,会通过fd数组传出两个文件描述符fd[0]和fd[1],其中fd[0]为读而打开,fd[1]为写而打开。从fd[0]中读的数据,就是往fd[1]中写的数据。

当父进程调用fork后,子进程继承了父进程的文件描述符fd[0]和fd[1]。这样就建立了父子进程之间的IPC通道。父进程往fd[1]中写数据时,子进程就可以通过fd[0]读到。

下面代码描述的是上图的流程

父进程

1:fork出自进程

2:从标准输入读入数据

3:将数据通过fd[1]写入管道

子进程

1:通过fd[0]从管道读入数据

2:将数据写到标准输出

#include <stdio.h>#include <unistd.h>int main () {int buflen;char* buffer[1024];pid_t pid;int fd[2];if (pipe(fd) < 0) {printf ("pipe error\n");return 1;}if ((pid = fork()) < 0) {printf ("pipe error\n");return 1;}if (pid > 0) {       //fatherclose (fd[0]);while ((buflen = read (STDIN_FILENO, buffer, 1024)) > 0) {write (fd[1], buffer, buflen);}return 0;}else {close (fd[1]);while ((buflen = read (fd[0], buffer, 1024)) > 0) {write (STDOUT_FILENO, buffer, buflen);}return 0;}}


 

图中1 2 3 4 5 6分别为:

1是父进程标准输入(STDIN_FILENO)

2是父进程的fd1[1]

3是子进程的fd1[0],同时也是子进程的标准输入

4是子进程的fd2[1],同时也是子进程的标准输出

5是父进程的fd2[0]

6是父进程的标准输出(STDOUT_FILENO)

父进程流程:

1:fork创建子进程

2:主循环中不断从标准输入中读取数据

3:通过fd1[1]将读入的数据写入管道

4:通过fd2[0]从管道中读入数据

5:将数据写到标准输出

子进程流程:

1:调用dup2函数复制文件描述符fd1[0]为标准输入

2:复制文件描述符fd2[1]为标准输出

3:调用execl函数执行新的程序coproces,进入coproces主循环,该程序由coproces.c编译而成,功能是英文字符大小写转换。

4:在coproces主循环中不断从标准输入读取数据

5:将数据中英文字符大小写转换后写入标准输出。

// coproces.c

#include <stdio.h>#include <unistd.h>int main () {char buffer[1024];int buflen;while ((buflen = read (STDIN_FILENO, buffer, 1024)) > 0) {int i  = 0;for (i = 0; i < buflen; ++i) {if (isupper (buffer[i])) {buffer[i] = tolower (buffer[i]);}else if (islower (buffer[i])) {buffer[i] = toupper (buffer[i]);}}write (STDOUT_FILENO, buffer, buflen);}}


 // main.c

#include <stdio.h>#include <unistd.h>#include <stdlib.h>int main () {pid_t pid;int fd1[2], fd2[2];int buflen;char buffer[1024];if (pipe (fd1) < 0 || pipe (fd2) < 0) {printf ("pipe error!\n");exit (1);}if ((pid = fork()) < 0) {printf ("fork error !\n");exit (1);}if (!pid) {       // child processclose (fd1[1]); // read onlyclose (fd2[0]); // write onlyif (STDIN_FILENO != fd1[0]) {if(STDIN_FILENO !=dup2 (fd1[0], STDIN_FILENO)) {printf ("error!\n");exit (1);}close (fd1[0]);}if (STDOUT_FILENO != fd2[1]) {if(STDOUT_FILENO != dup2 (fd2[1], STDOUT_FILENO)) {printf ("error!\n");exit (1);}close (fd2[1]);}if (execl ("./coproces", "coproces",(char*)0) < 0) {printf ("execl error\n");exit (1);}}// parent processclose (fd1[0]);  //write onlyclose (fd2[1]);  //read onlywhile ((buflen = read (STDIN_FILENO, buffer, 1024)) > 0) {if (buflen != write (fd1[1], buffer, buflen)) {printf ("write to fd1 error!\n");exit (1);}buflen = read (fd2[0], buffer, 1024);write (STDOUT_FILENO, buffer, buflen);}exit (0);}