进程间通信 | 管道通信Ⅱ

学术   科技   2023-05-15 06:17   北京  

通信示例

1. 父子进程之间

    父子进程之间可以通过匿名管道进行通信

    使用匿名管道进行通信的步骤:

(1)创建文件描述符   int  fds[2];

(2)将文件描述符号(fd)变成管道  pipe

(3)使用管道

(4)关闭文件描述符(fd)


    示例——使用匿名管道  父进程循环等待用户输入并写入管道 ,子进程循环读取管道内容并输出:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <string.h>
//使用匿名管道 父进程循环等待用户输入并写入管道 子进程循环读取管道内容并输出int main(){ //1. 创建文件描述符号 int fds[2]; fds[0] 读端 fds[1] 写端 int fds[2];
//2. 将文件描述符号(fd)变成管道 pipe int ret = pipe(fds); if(-1 == ret) printf("创建管道失败:%m\n"),exit(-1); printf("创建管道成功!\n"); //3. 使用管道 if(fork()) // 父进程 { char wbuff[1024] = {0}; // 根据用户输入向管道写内容 while(1) { scanf("%s",wbuff); write(fds[1],wbuff,strlen(wbuff)); sleep(1); } } else // 子进程 { char rbuff[1024] = {0}; // 循环读取管道内容 while(1) { sleep(1); int r = read(fds[0],rbuff,1023); if(r > 0){ rbuff[r]=0; printf(">> %s\n",rbuff); } } }
//4. 关闭文件描述符(fd) close(fds[0]); close(fds[1]); return 0;}

    运行结果:

2. 非父子进程之间

    非父子进程之间需要通过实名管道进行通信

    使用实名管道进行通信的步骤(非父子进程一般就是在两个文件中创建的不同进程,所以这里有两个文件):


文件A代码:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>
//文件A 数据写入端int main(){ //1.创建实名管道文件 int ret = mkfifo("test.pipe",0666); if(-1 == ret) printf("创建管道文件失败:%m\n"),exit(-1); printf("创建管道文件成功!\n"); //2.打开管道文件 int fd = open("test.pipe",O_WRONLY,0666); if(-1 == fd) printf("打开管道文件失败:%m\n"),unlink("test.pipe"),exit(-1); printf("打开管道文件成功!\n"); //3.循环向管道文件中写入数据 int n = 0; char buff[1024] = {0}; while(1) { sprintf(buff,"Linux,学了忘得好快!%d",++n); write(fd,buff,strlen(buff)); sleep(1); } //4.关闭管道 close(fd); //5.删除管道文件 unlink("test.pipe"); return 0;}

文件B代码:

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>//文件B  数据读取端int main(){    //2. 打开管道文件    int fd = open("test.pipe",O_RDONLY,0666);    if(-1 == fd) printf("文件打开失败:%m\n"),unlink("test.pipe"),exit(-1);    printf("文件打开成功!\n");    //3. 从管道文件中读取数据    int r = 0;    char buff[1024]={0};    while(1)    // 循环读取    {        r = read(fd,buff,1023);        // 打印读取的数据        if(r > 0)        {            buff[r] = 0;            printf(">> %s\n",buff);        }    }     //4. 关闭管道    close(fd);     return 0;}

验证效果

    上面两个文件分别命名为pipe_a.cpp和 pipe_b.cpp,编译产生的可执行文件分别为pipe_a 和 pipe_b:

    执行这两个程序需要打开两个终端,正确运行效果如下:

    执行时,需要运行pipe_a,因为pipe_a会创建管道文件,然后因为默认阻塞而等待读端从管道读数据(只是创建了管道文件,但是还没有open):

    如果先运行了pipe_b,会因为没有管道文件而退出程序:

    如果先关闭读取端,会导致写入端进程结束,因为管道“不读无法写”:

    先关闭写入端,读取端进程进入阻塞状态:

控制工程研习
好好学习,天天向上
 最新文章