如何利用管道进行进程间通信? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
bigshot
V2EX    程序员

如何利用管道进行进程间通信?

  •  
  •   bigshot 2018 年 5 月 1 日 2332 次点击
    这是一个创建于 2821 天前的主题,其中的信息可能已经有所发展或是发生改变。

    管道通信

    匿名管道

    创建匿名管道

    int pipe(int pipefd[2]); pipefd[0] : 表示读管道 pipefd[1] : 表示写管道 返回 0 表示成功,非零表示创建失败。

    代码事例

    //匿名管道 int main() { int fds[2]; int len; char buf[100]={}; if(pipe(fds)==-1) //创建管道 perror("pipe"),exit(1); while(fgets(buf,100,stdin)) { len = strlen(buf); if(write(fds[1],buf,len)==-1) //把内容写进管道 perror("write"),exit(1); memset(buf,0x00,sizeof(char)*100); if(read(fds[0],buf,len)==-1) //从管道里面读取内容到数组中 perror("read"),exit(1); if(write(1,buf,len)==-1) //把从管道里读出的内容写到标准输出 perror("write"),exit(1); } return 0; } 

    结果展示

    这里写图片描述

    日常运用事例 who | wc -l 这样的事例我们经常用到,用管道连接命令会令你得心应手。

    图片解析

    这里写图片描述

    ####利用管道进行父子进程通信 图片解析原理 这里写图片描述 代码示例:

    //父子进程通信 int main() { char buf[1024]="change world!\n"; int fds[2]; if(pipe(fds)==-1) perror("pipe"),exit(1); pid_t pid = fork(); //创建匿名管道 if(pid==0) { close(fds[0]); //关闭管道读描述符 if(write(fds[1],buf,1024)==-1) //写进管道 perror("write"),exit(1); close(fds[1]); exit(1); } else { memset(buf,0x00,1024); close(fds[1]); //关闭管道写描述符 if(read(fds[0],buf,1024)==-1) //从管道读内容 perror("read"),exit(1); if(write(1,buf,1024)==-1) perror("write"),exit(1); close(fds[0]); exit(1); } return 0; } 

    结果 这里写图片描述 详细过程图解 这里写图片描述

    ####管道读写规则

    当没有数据可读时

    • O_NONBLOCK disable:read 调用阻塞,即进程暂停执行,.一直等到有数据来到为止。
    • O_NONBLOCK enable:read 调用返回-1,errno 值为 EAGAIN。

    当管道满的时候

    • O_NONBLOCK disable:write 调用阻塞,直到有进程读.走数据
    • O_NONBLOCK enable:调用返回-1,errno 值为 EAGAIN
    • 如果所有管道写端对应的文件描述符被关闭,则 read 返回 0
    • 如果所有管道读端对应的文件描述符被关闭,则 write 操作会产生信号 SIGPIPE,进而可能导致 write 进程退出
    • 当要写.入的数据量不.大于 PIPE_BUF 时,linux 将保证写.入的原.子性。
    • 当要写.入的数据量.大于 PIPE_BUF 时,linux 将不再保证写.入的原.子性。

    管道特点

    • 只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常,一个管道由一个进程创建,然后该进程调用 fork,此后父、子进程之间就可应用该管道。
    • 管道提供流式服务
    • 一般而言,进程退出,管道释放,所以管道的生命周期随进程
    • 一般而言,内核会对管道操作进行同步与互斥管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道

    命名管道

    我们刚刚可以用匿名管道在父子进程之间通信,那如果是两个不想光的进程之间该如何通信呢?

    创建命名管道

    在命令行可以直接创建mkfifo filename 这里写图片描述 也可以在程序内部创建,相关函数 int mkfifo(const char *pathname, mode_t mode);

    代码示例:

    int main() { mkfifo("my.p",0644); return 0; } 

    这里写图片描述

    ####无关进程之间通信代码示例

    从标准输入读入内容进管道

    #include<string.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> int main() { mkfifo("my.p",0664); int outfd = open("my.p",O_WRONLY); if(outfd==-1) perror("open my.txt"),exit(1); char buf[1024]={}; int n = 0; while(fgets(buf,1024,stdin)) { write(outfd,buf,1024); memset(buf,0x00,1024); } close(outfd); 

    从管道中读内容,标准输出输出

    #include<string.h> #include<stdlib.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> int main() { int infd = open("my.p",O_RDONLY); if(infd==-1) perror("open my.p"),exit(1); char buf[1024]={}; int n = 0; while((n = read(infd,buf,1024))>0) { write(1,buf,n); memset(buf,0x00,1024); } close(infd); unlink("my.p"); //删除管道 return 0; } 

    运行结果: 这里写图片描述 这里就利用管道实现了两个无关进程之间的通信。

    ###匿名管道和命名管道的区别。

    • 匿名管道由 pipe 函数创建并打开。
    • 命名管道由 mkfifo 函数创建,打开用 open
    • FIFO (命名管道)与 pipe (匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。
    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana nbsp;   3435 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 04:50 PVG 12:50 LAX 20:50 JFK 23:50
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86