日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

进程间通信(IPC机制)——管道

發(fā)布時間:2024/4/17 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进程间通信(IPC机制)——管道 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.管道的特點

(1)無論有名還是無名,寫入管道的數(shù)據(jù)都在內(nèi)存中。
(2)管道是一種半雙工通信方式(通信方式有單工(固定接收方發(fā)送方,接收方只能接收,發(fā)送方只能發(fā)送)、半雙工(如同對講機(jī),兩端可以切換寫入和接收)、全雙工(每端都可以接收和寫入,且可以同時進(jìn)行))。
(3)有名和無名管道的區(qū)別:有名可以在任意進(jìn)程間使用,而無名只能在父子進(jìn)程間。
(4)對于管道,我們只能以只讀打開或者只寫打開。
(5)有名管道得需要讀和寫都打開,否則只以讀打開或者只以寫打開都會阻塞。
(6)管道中沒有數(shù)據(jù)時,讀管道read會發(fā)生阻塞,直至管道被寫入數(shù)據(jù),讀出數(shù)據(jù),再次阻塞。如果寫端被關(guān)閉,讀端read返回值會成為0。如果讀端被關(guān)閉,寫端向管道寫入數(shù)據(jù)后會自動退出。
(7)管道寫滿后,寫端會阻塞。
(8)由于管道的數(shù)據(jù)都在內(nèi)存中,所以查看管道大小總是0。
管道的實現(xiàn):

寫入從頭指針開始,讀取從尾指針開始。寫入之后,頭指針挪動,讀取之后尾指針挪動。如果是頭指針趕上尾指針,那么管道被寫滿,寫就會被阻塞。如果是尾指針趕上頭指針,那么管道為空,read阻塞。
管道可以用來在兩個進(jìn)程之間傳遞數(shù)據(jù),如: ps -ef | grep “bash”, 其中‘|’就是管道,其作用就是將 ps 命令的結(jié)果寫入管道文件,然后 grep 再從管道文件中讀出該數(shù)據(jù)進(jìn)行過濾。
管道大小是可以查看的,如下圖可以看到管道512字節(jié)為一個單位,乘以8就是整個管道大小。

2.有名管道

2.1有名管道的創(chuàng)建和頭文件

有名管道可以在任意兩個進(jìn)程之間通信
有名管道的創(chuàng)建:
(1)命令創(chuàng)建: mkfifo + 管道名
(2)系統(tǒng)調(diào)用創(chuàng)建

#include <sys/types.h> #include <sys/stat.h> //filename 是管道名 mode 是創(chuàng)建的文件訪問權(quán)限 int mkfifo( const char *filename, mode_t mode);

2.2有名管道的使用

進(jìn)程 a 從鍵盤獲取的數(shù)據(jù)循環(huán)傳遞給另一個進(jìn)程 b。
我們可以用創(chuàng)建一個文件,a從鍵盤獲取字符串存放到文件中,b從文件中讀取。但是文件是存在磁盤上的,速度沒有管道快,而且從文件讀不到數(shù)據(jù)不會等待,但是管道不一樣,b從管道讀不到數(shù)據(jù)會阻塞,直到a又向管道中寫入數(shù)據(jù)。

首先用命令mkfifo+管道名稱創(chuàng)建管道

寫端代碼:

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<assert.h> #include<fcntl.h> #include<sys/stat.h>int main() {int fd = open("fifo",O_WRONLY);assert(fd != -1);printf("open FIFO success\n");while(1){printf("please input:\n");char buff[128] = {0};fgets(buff,128,stdin);write(fd,buff,strlen(buff)-1);if(strncmp(buff,"end",3)==0){break;}}close(fd);exit(0); }

讀端代碼:

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<assert.h> #include<fcntl.h> #include<sys/stat.h>int main() {int fd = open("fifo",O_RDONLY);assert(fd != -1);printf("FIFO open success\n");while(1){char buff[128] = {0};int n = read(fd,buff,127);if(n <= 0 || (strncmp(buff, "end", 3)==0)){break;}printf("%s\n",buff);}close(fd);exit(0); }

(1)如果讀端或者寫端先打開,那么將會在open阻塞住 ,直至另一端也打開管道。
(2)寫端和讀端都打開后,讀端會在read處阻塞,寫端向管道中寫入數(shù)據(jù)后,讀端才正常執(zhí)行read,執(zhí)行完繼續(xù)在read阻塞。
(3)如果讀端關(guān)閉,寫端在向管道輸入數(shù)據(jù)后會觸發(fā)信號(SIGPIPE)自動退出。
(4)如果寫端關(guān)閉,讀端read函數(shù)值會返回0。
當(dāng)寫端和讀端都在打開著,管道中的數(shù)據(jù)如果沒有及時讀出,不會消失。比如將讀端加上休眠10s,代碼如下:

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<assert.h> #include<fcntl.h> #include<sys/stat.h>int main() {int fd = open("fifo",O_RDONLY);assert(fd != -1);printf("FIFO open success\n");while(1){char buff[128] = {0};int n = read(fd,buff,127);if(n <= 0 || (strncmp(buff, "end", 3)==0)){break;}printf("%s\n",buff);sleep(10);}close(fd);exit(0); }

寫端和讀端執(zhí)行情況:


發(fā)現(xiàn),在讀端還沒來得及讀走管道數(shù)據(jù)的時候?qū)懚嗽俅蜗蚬艿缹懭霐?shù)據(jù),管道中沒讀走的數(shù)據(jù)會被讀端下一次讀走。

3.無名管道

無名管道主要應(yīng)用于父子進(jìn)程間的通信。
無名管道的創(chuàng)建:

#include <unistd.h> 2. /* 3. pipe()成功返回 0,失敗返回-1 4. fds[0]是管道讀端的描述符 5. fds[1]是管道寫端的描述符 6. */ 7. int pipe( int fds[2]);

代碼演示:

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<assert.h>int main() {int fd[2];int res = pipe(fd);assert(res != -1);pid_t pid = fork();assert(pid != -1);if(pid == 0){close(fd[1]);char buff[128] = {0};read(fd[0],buff,127);printf("child read:%s\n",buff);close(fd[0]);}else{close(fd[0]);char buff[128] = {0};printf("please input(less 128):\n");fgets(buff,128,stdin);write(fd[1],buff,strlen(buff)-1);close(fd[1]);}exit(0); }

執(zhí)行結(jié)果:

總結(jié)

以上是生活随笔為你收集整理的进程间通信(IPC机制)——管道的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。