[OS] 进程间通信--管道
管道是單向的、先進(jìn)先出的、無(wú)結(jié)構(gòu)的、固定大小的字節(jié)流,它把一個(gè)進(jìn)程的標(biāo)準(zhǔn)輸出和另一個(gè)進(jìn)程的標(biāo)準(zhǔn)輸入連接在一起。寫(xiě)進(jìn)程在管道的尾端寫(xiě)入數(shù)據(jù),讀進(jìn)程在管道的首端讀出數(shù)據(jù)。數(shù)據(jù)讀出后將從管道中移走,其它讀進(jìn)程都不能再讀到這些數(shù)據(jù)。管道提供了簡(jiǎn)單的流控制機(jī)制。進(jìn)程試圖讀空管道時(shí),在數(shù)據(jù)寫(xiě)入管道前,進(jìn)程將一直阻塞。同樣,管道已經(jīng)滿時(shí),進(jìn)程再試圖寫(xiě)管道,在其它進(jìn)程從管道中移走數(shù)據(jù)之前,寫(xiě)進(jìn)程將一直處于阻塞狀態(tài)。
管道主要用于不同進(jìn)程間通信。
下面介紹管道的使用方法:
管道創(chuàng)建:
1 #include <unistd.h> 2 int pipe(int fd[2]);它接收一個(gè)參數(shù),也就是包括兩個(gè)整數(shù)的數(shù)組。如果系統(tǒng)調(diào)用成功,此數(shù)組將包括管道使用的兩個(gè)文件描述符。創(chuàng)建一個(gè)管道之后,一般情況下進(jìn)程將產(chǎn)生一個(gè)新的進(jìn)程。
系統(tǒng)調(diào)用:pipe();
原型:int pipe(int fd[2]);
返回值:成功返回0,失敗返回-1。
fd[1]寫(xiě),fd[0]讀。
如下圖所示,管道是在內(nèi)核空間的內(nèi)存中創(chuàng)建的。
單個(gè)進(jìn)程的管道幾乎沒(méi)有任何用處,通常,調(diào)用pipe的進(jìn)程接著調(diào)用fork,這樣就創(chuàng)建了父子進(jìn)程間的管道。
1 #include <unistd.h> 2 #include<stdio.h> 3 #include<sys/types.h> 4 #include<sys/wait.h> 5 6 int main() 7 { 8 int fd[2]; 9 char buf[80]; 10 pid_t pid; 11 pipe(fd); 12 pid = fork(); 13 if(pid>0) 14 {//父進(jìn)程 15 printf("Father thread\n"); 16 char s[]="Hello\n"; 17 write(fd[1],s,sizeof(s)); 18 close(fd[0]); 19 close(fd[1]); 20 } 21 else if(pid==0) 22 { 23 printf("Child Thread\n"); 24 read(fd[0],buf,sizeof(buf)); 25 printf("%s\n",buf); 26 close(fd[0]); 27 close(fd[1]); 28 } 29 waitpid(pid,NULL,0);//等待子進(jìn)程結(jié)束 30 return 0; 31 }運(yùn)行結(jié)果:
Father thread Child Thread Hello當(dāng)管道的一端關(guān)閉時(shí):
當(dāng)讀一個(gè)寫(xiě)端關(guān)閉的管道時(shí),則認(rèn)為已經(jīng)讀到了數(shù)據(jù)的末尾,讀函數(shù)返回的讀出字節(jié)數(shù)為0;
當(dāng)寫(xiě)一個(gè)讀端關(guān)閉的管道時(shí),向管道中寫(xiě)入數(shù)據(jù)的進(jìn)程將收到內(nèi)核傳來(lái)的SIFPIPE信號(hào),應(yīng)用程序可以處理該信號(hào),也可以忽略(默認(rèn)動(dòng)作則是應(yīng)用程序終止)。
從管道中讀取數(shù)據(jù):
當(dāng)管道的寫(xiě)端存在時(shí),如果請(qǐng)求的字節(jié)數(shù)目大于PIPE_BUF,則返回管道中現(xiàn)有的數(shù)據(jù)字節(jié)數(shù),如果請(qǐng)求的字節(jié)數(shù)目不大于PIPE_BUF,則返回管道中現(xiàn)有數(shù)據(jù)字節(jié)數(shù)(此時(shí),管道中數(shù)據(jù)量小于請(qǐng)求的數(shù)據(jù)量);或者返回請(qǐng)求的字節(jié)數(shù)(此時(shí),管道中數(shù)據(jù)量不小于請(qǐng)求的數(shù)據(jù)量)。注:PIPE_BUF在include/linux/limits.h中定義。
向管道中寫(xiě)入數(shù)據(jù):
向管道中寫(xiě)入數(shù)據(jù)時(shí),linux將不保證寫(xiě)入的原子性,管道緩沖區(qū)一有空閑區(qū)域,寫(xiě)進(jìn)程就會(huì)試圖向管道寫(xiě)入數(shù)據(jù)。如果讀進(jìn)程不讀走管道緩沖區(qū)中的數(shù)據(jù),那么寫(xiě)操作將一直阻塞。
管道因?yàn)闆](méi)有名字所以只能用于具有親緣關(guān)系的進(jìn)程,而命名管道(FIFO)則克服了這個(gè)限制。
命名管道和一般的管道基本相同,但也有一些顯著的不同:
·命名管道是在文件系統(tǒng)中作為一個(gè)特殊的設(shè)備文件而存在的。
·不同祖先的進(jìn)程之間可以通過(guò)管道共享數(shù)據(jù)。
·當(dāng)共享管道的進(jìn)程執(zhí)行完所有的I/O操作以后,命名管道將繼續(xù)保存在文件系統(tǒng)中以便以后使用。
·通過(guò)FIFO,不相關(guān)的進(jìn)程也可以交換數(shù)據(jù)。
下面是命名管道的使用方法:
命名管道創(chuàng)建:
1 #include <sys/types.h> 2 #include<sys/stat.h> 3 Int mkfifo(const char * pathname, mode_t mode);返回:成功返回0,出錯(cuò)返回-1。
注:一旦已經(jīng)用mkfifo創(chuàng)建一個(gè)FIFO,就可以用open打開(kāi)。一般的文件I/O函數(shù)close, read , write等都可以用于FIFO。
轉(zhuǎn)載于:https://www.cnblogs.com/lca1826/p/6538221.html
總結(jié)
以上是生活随笔為你收集整理的[OS] 进程间通信--管道的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 浦发信用卡免息期最长多少天
- 下一篇: office 2013 安装问题