进程间的通信——无名管道
進程間的通信——無名管道
宗旨:技術的學習是有限的,分享的精神是無限的。
一、進程間的通信
(1)同主機進程間數據交互機制:無名管道(PIPE),有名管道(FIFO)、消息隊列和共享內存。無名管道多用于親緣關系進程間通信,無名管道可用于任意同主機進程間通信,但管道是單向的,會出現同時讀寫問題。消息隊列可以實現同主機上任意多進程間通信,但存放的數據量很有限,應用于少量的數據傳遞。共享內存可實現同主機任意進程間大數據通信,但共享空間數據訪問時存在競爭問題。
(2)同主機進程間同步機制:信號量(semaphore)
(3)同主機進程間異步機制:信號(signal)
(4)網絡主機間數據交互機制:套接字(socket)
?
二、無名管道
? ? ? ? 使用管道將一個命令的輸出作為另一個命令的輸入(運行時一個命令將創建一個進程),這種管道是臨時的,命令執行完后將自動消失,這類管道稱為無名管道。
? ? ? ? 無名管道是一種特殊類型的文件,在內核中對應的資源即一段特殊內存空間,內核在這段空間中以循環隊列的方式臨時存入一個進程發給另一個進程的信息,這段內核空間完全由操作系統管理和維護,應用程序只能通過系統調用訪問。
? ? ? ? 無名管道和普通文件:無名管道的內核資源在進程退出時自動釋放;不能像普通文件一樣存儲大量常規信息;編程應用中和普通文件有一樣的特點,可以read/write。
1、 pipe
——創建無名管道,單向傳輸
(1) 函數原型
? ? ? ?#include <unistd.h>
?????? int pipe(int pipes[2]);
(2) 函數參數
? ? ? ? pipes:管道的讀端和寫端【pipes[0]——讀出,pipes[1]——寫入】
(3) 返回值
? ? ? ? 執行成功,存儲兩個文件描述符于pipes中,返回0,調用失敗返回-1
2、 兩進程通信
?????? 父進程調用pipe函數開辟管道,得到兩個文件描述符指向管道的兩端;父進程調用fork函數創建子進程,那么子進程也有兩個文件描述符指向管道兩端;父進程關閉管道讀端,子進程關閉管道寫端,父進程可以往管道里寫,子進程可以從管道里讀,管道是用環形隊列實現的,數據從寫端流入從讀端流出,這樣就實現了進程間通信。
#include<stdlib.h> #include<unistd.h>#defineMAXLINE 80in tmain(void) {int n;int fd[2];pid_t pid;char line[MAXLINE];if (pipe(fd) < 0) // 開辟管道{perror("pipe");exit(1);}if ((pid = fork()) < 0) // 創建子進程{perror("fork");exit(1);}if (pid > 0) /* parent */{close(fd[0]);write(fd[1], "hello world\n", 12);wait(NULL);}else /* child */{close(fd[1]);n = read(fd[0], line, MAXLINE);write(STDOUT_FILENO, line, n);}return 0; }3、 注意4種特殊情況(都是阻塞I/O操作,沒有設置O_NONBLOCK標志)
(1) 如果所有指向管道寫端的文件描述符都關閉了(管道寫端的引用計數等于0),而仍然有進程 從管道的讀端讀數據,那么管道中剩余的數據都被讀取后,再次read會返回0,就像讀到文件 末尾一樣。
(2) 如果有指向管道寫端的文件描述符沒關閉(管道寫端的引用計數大于0),而持有管道寫端的 進程也沒有向管道中寫數據,這時有進程從管道讀端讀數據,那么管道中剩余的數據都被讀 取后,再次read會阻塞,直到管道中有數據可讀了才讀取數據并返回。
(3) 如果所有指向管道讀端的文件描述符都關閉了(管道讀端的引用計數等于0),這時有進程向管道的寫端write,那么該進程會收到信號SIGPIPE,通常會導致進程異常終止。
(4) 如果有指向管道讀端的文件描述符沒關閉(管道讀端的引用計數大于0),而持有管道讀端的進程也沒有從管道中讀數據,這時有進程向管道寫端寫數據,那么在管道被寫滿時再次write會阻塞,直到管道中有空位置了才寫入數據并返回。
總結
以上是生活随笔為你收集整理的进程间的通信——无名管道的全部內容,希望文章能夠幫你解決所遇到的問題。