無名管道
無名管道是半雙工的,就是對於一個管道來講,只能讀,或者寫。
無名管道只能在相關的,有共同祖先的進程間使用(即一般用戶父子進程)。
一個fork或者execve調用創建的子進程繼承了父進程的文件描述符。
打開和關閉管道 int pipe(int filedes[2]); 在你從一個管道中讀出或者寫入數據,這個管道必須存在。 如果成功建立了管道,則會打開兩個文件描述符,並把他們的值保存在一個整數數組中。 第一個文件描述符用於讀取數據,第二個文件描述符用於寫入數據。
管道的兩個文件描述符相當於管道的兩端,一端只負責讀數據,一端只負責寫數據 如果出錯返回-1,同時設置errno 關閉一個文件描述符用close()函數
關閉一個管道的所有文件描述符等於關閉這個管道(不能讀不能寫) pipe()函數打開管道一般不會失敗
讀寫管道
讀寫管道與讀寫普通文件方式一樣,調用write與read函數即可。
幾乎不會在一個進程中打開一個管道僅供進程自己使用,管道是用來交換數據的。
因為一個進程已經能夠訪問它要通過管道共享的數據,和自己共享數據是沒有意義的。
試圖對一個管道的某一端同時進行讀寫操作是一個嚴重的錯誤。
//無名管道 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main(int arg, char * args[]) { //定義文件描述符數組 int fdarr[2] = { 0 }; int no = 0; int status; //create the conduit 創建一個管道 並且打開兩個文件描述符 //管道中,第一個文件描述符只讀,第二個文件描述符只寫 no = pipe(fdarr); if (no == -1) { printf("pipe() is failed ! message :%s\n", strerror(errno)); return -1; } //創建父子進程 pid_t child = fork(); if (child == -1) { printf("system is game over !\n"); return -1; } //定義緩存字符串數組 char buf[100] = { 0 }; if (child == 0) { /* 管道和文件一樣,文件read函數以O_RDONLY方式打開也會阻塞,但是文件數據在本地,讀取非常快,感覺不到阻塞, 但是管道以O_RDONLY方式打開,會阻塞進程,read()函數會等待管道另一端寫入數據,直到另一端關閉文件描述符 */ //關閉子進程中的寫文件描述符--對於父子進程共享文件描述符,只在單個進程中關閉,只能將文件描述符引用減一, //因為父子進程中,文件描述符被引用了兩次,所以需要在父子進程中分別關閉,才能使文件描述符引用次數減一 close(fdarr[1]); while (read(fdarr[0], buf, sizeof(buf)) > 0) { printf("%s", buf); //清空緩存區 memset(buf, 0, sizeof(buf)); } //關閉子進程中讀文件描述符 close(fdarr[0]); } else { //關閉父進程中的讀描述符 close(fdarr[0]); //將鍵盤輸入數據寫入到管道中 strcpy(buf,"fly on air!\n"); write(fdarr[1], buf, strlen(buf)); //關閉管道寫文件描述符 close(fdarr[1]); //等待子進程結束 wait(&status); printf("child process is close ! message :%d\n", WEXITSTATUS(status)); } return 10; }