[OS] 进程间通信--管道
管道是單向的、先進先出的、無結構的、固定大小的字節流,它把一個進程的標準輸出和另一個進程的標準輸入連接在一起。寫進程在管道的尾端寫入數據,讀進程在管道的首端讀出數據。數據讀出后將從管道中移走,其它讀進程都不能再讀到這些數據。管道提供了簡單的流控制機制。進程試圖讀空管道時,在數據寫入管道前,進程將一直阻塞。同樣,管道已經滿時,進程再試圖寫管道,在其它進程從管道中移走數據之前,寫進程將一直處于阻塞狀態。
管道主要用于不同進程間通信。
下面介紹管道的使用方法:
管道創建:
1 #include <unistd.h> 2 int pipe(int fd[2]);它接收一個參數,也就是包括兩個整數的數組。如果系統調用成功,此數組將包括管道使用的兩個文件描述符。創建一個管道之后,一般情況下進程將產生一個新的進程。
系統調用:pipe();
原型:int pipe(int fd[2]);
返回值:成功返回0,失敗返回-1。
fd[1]寫,fd[0]讀。
如下圖所示,管道是在內核空間的內存中創建的。
單個進程的管道幾乎沒有任何用處,通常,調用pipe的進程接著調用fork,這樣就創建了父子進程間的管道。
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 {//父進程 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);//等待子進程結束 30 return 0; 31 }運行結果:
Father thread Child Thread Hello當管道的一端關閉時:
當讀一個寫端關閉的管道時,則認為已經讀到了數據的末尾,讀函數返回的讀出字節數為0;
當寫一個讀端關閉的管道時,向管道中寫入數據的進程將收到內核傳來的SIFPIPE信號,應用程序可以處理該信號,也可以忽略(默認動作則是應用程序終止)。
從管道中讀取數據:
當管道的寫端存在時,如果請求的字節數目大于PIPE_BUF,則返回管道中現有的數據字節數,如果請求的字節數目不大于PIPE_BUF,則返回管道中現有數據字節數(此時,管道中數據量小于請求的數據量);或者返回請求的字節數(此時,管道中數據量不小于請求的數據量)。注:PIPE_BUF在include/linux/limits.h中定義。
向管道中寫入數據:
向管道中寫入數據時,linux將不保證寫入的原子性,管道緩沖區一有空閑區域,寫進程就會試圖向管道寫入數據。如果讀進程不讀走管道緩沖區中的數據,那么寫操作將一直阻塞。
管道因為沒有名字所以只能用于具有親緣關系的進程,而命名管道(FIFO)則克服了這個限制。
命名管道和一般的管道基本相同,但也有一些顯著的不同:
·命名管道是在文件系統中作為一個特殊的設備文件而存在的。
·不同祖先的進程之間可以通過管道共享數據。
·當共享管道的進程執行完所有的I/O操作以后,命名管道將繼續保存在文件系統中以便以后使用。
·通過FIFO,不相關的進程也可以交換數據。
下面是命名管道的使用方法:
命名管道創建:
1 #include <sys/types.h> 2 #include<sys/stat.h> 3 Int mkfifo(const char * pathname, mode_t mode);返回:成功返回0,出錯返回-1。
注:一旦已經用mkfifo創建一個FIFO,就可以用open打開。一般的文件I/O函數close, read , write等都可以用于FIFO。
轉載于:https://www.cnblogs.com/lca1826/p/6538221.html
總結
以上是生活随笔為你收集整理的[OS] 进程间通信--管道的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浦发信用卡免息期最长多少天
- 下一篇: office 2013 安装问题