利用管道实现进程间通信
管道通信
匿名管道
創(chuàng)建匿名管道
int pipe(int pipefd[2]);
pipefd[0] : 表示讀管道
pipefd[1] : 表示寫管道
返回 0表示成功,非零表示創(chuàng)建失敗。
代碼事例
//匿名管道 int main() {int fds[2];int len;char buf[100]={};if(pipe(fds)==-1) //創(chuàng)建管道perror("pipe"),exit(1);while(fgets(buf,100,stdin)){ len = strlen(buf);if(write(fds[1],buf,len)==-1) //把內(nèi)容寫進管道perror("write"),exit(1);memset(buf,0x00,sizeof(char)*100);if(read(fds[0],buf,len)==-1) //從管道里面讀取內(nèi)容到數(shù)組中perror("read"),exit(1);if(write(1,buf,len)==-1) //把從管道里讀出的內(nèi)容寫到標(biāo)準(zhǔn)輸出perror("write"),exit(1);} return 0; }結(jié)果展示
日常運用事例
who | wc -l
這樣的事例我們經(jīng)常用到,用管道連接命令會令你得心應(yīng)手。
圖片解析
利用管道進行父子進程通信
圖片解析原理
代碼示例:
結(jié)果
詳細(xì)過程圖解
管道讀寫規(guī)則
當(dāng)沒有數(shù)據(jù)可讀時
- O_NONBLOCK disable:read調(diào)用阻塞,即進程暫停執(zhí)行,.一直等到有數(shù)據(jù)來到為止。
- O_NONBLOCK enable:read調(diào)用返回-1,errno值為EAGAIN。
當(dāng)管道滿的時候
- O_NONBLOCK disable: write調(diào)用阻塞,直到有進程讀.走數(shù)據(jù)
- O_NONBLOCK enable:調(diào)用返回-1,errno值為EAGAIN
- 如果所有管道寫端對應(yīng)的文件描述符被關(guān)閉,則read返回0
- 如果所有管道讀端對應(yīng)的文件描述符被關(guān)閉,則write操作會產(chǎn)生信號SIGPIPE,進而可能導(dǎo)致write進程退出
- 當(dāng)要寫.入的數(shù)據(jù)量不.大于PIPE_BUF時,linux將保證寫.入的原.子性。
- 當(dāng)要寫.入的數(shù)據(jù)量.大于PIPE_BUF時,linux將不再保證寫.入的原.子性。
管道特點
- 只能?用于具有共同祖先的進程(具有親緣關(guān)系的進程)之間進?行通信;通常,一個管道由一個進程創(chuàng)建,然后該進程調(diào)?用fork,此后?父、?子進程之間就可應(yīng)?用該管道。
- 管道提供流式服務(wù)
- 一般?而?言,進程退出,管道釋放,所以管道的?生命周期隨進程
一般?而?言,內(nèi)核會對管道操作進?行同步與互斥管道是半雙?工的,數(shù)據(jù)只能向?一個?方向流動;需要雙?方通信時,需要建?立起兩個管道
命名管道
我們剛剛可以用匿名管道在父子進程之間通信,那如果是兩個不想光的進程之間該如何通信呢?
創(chuàng)建命名管道
在命令行可以直接創(chuàng)建mkfifo filename
也可以在程序內(nèi)部創(chuàng)建,相關(guān)函數(shù)
int mkfifo(const char *pathname, mode_t mode);
代碼示例:
int main() {mkfifo("my.p",0644);return 0; }無關(guān)進程之間通信代碼示例
從標(biāo)準(zhǔn)輸入讀入內(nèi)容進管道
#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);從管道中讀內(nèi)容,標(biāo)準(zhǔn)輸出輸出
#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; }運行結(jié)果:
這里就利用管道實現(xiàn)了兩個無關(guān)進程之間的通信。
匿名管道和命名管道的區(qū)別。
- 匿名管道由pipe函數(shù)創(chuàng)建并打開。
- 命名管道由mkfifo函數(shù)創(chuàng)建,打開?用open
- FIFO(命名管道)與pipe(匿名管道)之間唯一的區(qū)別在它們創(chuàng)建與打開的?方式不同,一但這些工作完成之后,它們具有相同的語義。
轉(zhuǎn)載于:https://www.cnblogs.com/zhonglongbo/p/8976730.html
總結(jié)
以上是生活随笔為你收集整理的利用管道实现进程间通信的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阮一峰:Flex 布局教程
- 下一篇: hihocoder-Week200-Sh