进程间的通信之1-----管道
生活随笔
收集整理的這篇文章主要介紹了
进程间的通信之1-----管道
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
進(jìn)程間的通信之1-----管道
1、標(biāo)準(zhǔn)流管道
- 像文件操作有標(biāo)準(zhǔn) io 流一樣, 管道也支持文件流模式。 用來創(chuàng)建連接到另一進(jìn)程的管道, 是通過函數(shù) popen 和 pclose。
函數(shù)原型: #include <stdio.h> FILE* popen(const char* command, const char* open_mode); int pclose(FILE* fp);
函數(shù) popen(): 允許一個(gè)程序?qū)⒘硪粋€(gè)程序作為新進(jìn)程來啟動(dòng), 并可以傳遞數(shù)據(jù)給它或 者通過它接收數(shù)據(jù)。 command 字符串是要運(yùn)行的程序名。 open_mode 必須是“r” 或“w” 。 注意:對(duì)于普通的管道(單工的)就像通信的雙方一樣,若一端為讀屬性,則相對(duì)于的另一端只能寫,反之。其他類型的半雙工的、或全雙工--如套接字管道,除外。 函數(shù) pclose(): 用 popen 啟動(dòng)的進(jìn)程結(jié)束時(shí), 我們可以用 pclose 函數(shù)關(guān)閉與之關(guān)聯(lián)的文 件流。
例子:Example1: 從標(biāo)準(zhǔn)管道流中讀取,并打印/etc/profile 的內(nèi)容 #include <stdio.h> int main() { ?????FILE* fp = popen("cat /etc/profile", "r"); ?????char buf[512] = {0}; ?????while(fgets(buf, sizeof(buf), fp)) ?????{ ? ?? ?????puts(buf); ?????} ?????pclose(fp); ?????return 0; }
eg2: 寫到標(biāo)準(zhǔn)管道流并統(tǒng)計(jì)buf單詞數(shù)(被調(diào)用程序必須阻塞等待標(biāo)準(zhǔn)輸入) #include<stdio.h> int main() { ?????char buf[]={"aaa bbb ccc ddd eee fff ggg hhh"}; ?????FILE *fp = popen("wc -w", "w"); ?????fwrite(buf, sizeof(buf), 1, fp); ? ?? pclose(fp); ?????return 0; }
2、無名管道(PIPE)
- 管道是 linux 進(jìn)程間通信的一種方式, 如命令 ps -ef | grep ntp
- 無名管道的特點(diǎn):
-
- 1 、只能在親緣關(guān)系進(jìn)程間通信( 父子或兄弟)
- 2 、半雙工( 固定的讀端和固定的寫端)
- 3 、他是特殊的文件, 可以用 read、 write 等, 只能在內(nèi)存中
管道函數(shù)原型: #include <unistd.h> int pipe(int fds[2]);
- 管道在程序中用一對(duì)文件描述符表示, 其中一個(gè)文件描述符有可讀屬性, 一個(gè)有可寫的屬性。 fds[0]是讀, fds[1]是寫。
- 函數(shù) pipe 用于創(chuàng)建一個(gè)無名管道,成功返回 0, 否則返回-1。
- 通過調(diào)用 pipe 獲取這對(duì)打開的文件描述符后,一個(gè)進(jìn)程就可以從fds[0]中讀數(shù)據(jù),而另一個(gè)進(jìn)程就可以往fds[1]中寫數(shù)據(jù)。當(dāng)然兩進(jìn)程間必須有繼承關(guān)系,才能繼承這對(duì)打開的文件描述符。
- 管道不象真正的物理文件,不是持久的,即兩進(jìn)程終止后,管道也自動(dòng)消失了。
- 管道兩端的關(guān)閉是有先后順序的,如果先關(guān)閉寫端則從另一端讀數(shù)據(jù)時(shí),read函數(shù)將返回0,表示管道已經(jīng)關(guān)閉;但是如果先關(guān)閉讀端,則從另一端寫數(shù)據(jù)時(shí),將會(huì)使寫數(shù)據(jù)的進(jìn)程接收到SIGPIPE信號(hào),如果寫進(jìn)程不對(duì)該信號(hào)進(jìn)行處理,將導(dǎo)致寫進(jìn)程終止,如果寫進(jìn)程處理了該信號(hào),則寫數(shù)據(jù)的write函數(shù)返回一個(gè)負(fù)值,表示管道已經(jīng)關(guān)閉。
eg: #include <signal.h> #include <stdio.h> #include <string.h> #include <unistd.h> int main() { ?????int fds[2]; ?????pipe(fds); //注釋掉這部分將導(dǎo)致寫進(jìn)程被信號(hào)SIGPIPE終止 ?????sigset_t setSig; ?????sigemptyset(&setSig); ?????sigaddset(&setSig,SIGPIPE); ?????sigprocmask(SIG_BLOCK,&setSig,NULL); ?????char szBuf[10] = {0}; ?????if(fork() == 0){ ? ? ? ? ??close(fds[1]);//子關(guān)閉寫 ? ?? ?????sleep(2);//確保父關(guān)閉讀 ? ?? ?????if(read(fds[0], szBuf, sizeof(szBuf)) > 0) ? ? ? ? ? ?????puts(szBuf); ? ? ? ? ? ?????close(fds[0]);//子關(guān)閉讀 ? ? ?}else{ ? ?? ?????close(fds[0]);//父關(guān)閉讀 ? ?? ?????write(fds[1], "hello", 6); ? ?? ?????wait(NULL); ? ?? ?????write(fds[1], "world", 6);//子的讀關(guān)閉, 父還在寫 ? ?? ?????close(fds[1]);//父關(guān)閉寫 ?????} ?????return 0; }
3、命名管道(FIFO)
- 無名管道只能在親緣關(guān)系的進(jìn)程間通信大大限制了管道的使用, 有名管道突破了這個(gè)限制, 通過指定路徑名的范式實(shí)現(xiàn)不相關(guān)進(jìn)程間的通信
1. 用函數(shù)創(chuàng)建和刪除 FIFO 文件
- 創(chuàng)建 FIFO 文件的函數(shù)原型:
- #include <sys/types.h>
- #include <sys/stat.h>
- int mkfifo(const char *pathname, mode_t mode);
?????參數(shù) pathname 為要?jiǎng)?chuàng)建的 FIFO 文件的全路徑名; ?????參數(shù) mode 為文件訪問權(quán)限 ?????如果創(chuàng)建成功, 則返回 0, 否則-1。
- 刪除FIFO文件的函數(shù)原型為:
- #include <unistd.h>
- int unlink(const char *pathname); ? //是解除硬鏈接數(shù),也可用于其他文件移除。
2. ?用命令創(chuàng)建和刪除FIFO文件
- 用命令mkfifo創(chuàng)建 不能重復(fù)創(chuàng)建
- 用命令unlink刪除
- 創(chuàng)建完畢之后, 就可以訪問FIFO文件了:
-
- 一個(gè)終端: cat < myfifo
- 另一個(gè)終端: echo “hello” > myfifo
3、如果以讀取方式打開 FIFO, 并且還沒有其它進(jìn)程以寫入方式打開 FIFO, open 函數(shù)將被阻塞; 同樣, 如果以寫入方式打開 FIFO, 并且還沒其它進(jìn)程以讀取方式 FIFO, open 函數(shù)也將被阻塞。與 PIPE 相同, 關(guān)閉 FIFO 時(shí), 如果先關(guān)讀取端, 將導(dǎo)致繼續(xù)往 FIFO 中寫數(shù)據(jù)的進(jìn)程接收 SIGPIPE 的信號(hào)。
總結(jié)
以上是生活随笔為你收集整理的进程间的通信之1-----管道的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF:WPF显示PDF文档
- 下一篇: 命名实体识别以及词性自动标注