一、整體大綱

二、進(jìn)程間通信概念及方法
Linux環(huán)境下,進(jìn)程地址空間相互獨(dú)立,每個(gè)進(jìn)程各自有不同的用戶地址空間。任何一個(gè)進(jìn)程的全局變量在另一個(gè)進(jìn)程中都看不到,所以進(jìn)程和進(jìn)程之間不能相互訪問,要交換數(shù)據(jù)必須通過內(nèi)核,在內(nèi)核中開辟一塊緩沖區(qū),進(jìn)程1把數(shù)據(jù)從用戶空間拷到內(nèi)核緩沖區(qū),進(jìn)程2再?gòu)膬?nèi)核緩沖區(qū)把數(shù)據(jù)讀走,內(nèi)核提供的這種機(jī)制稱為進(jìn)程間通信(IPC,InterProcess Communication)。
在進(jìn)程間完成數(shù)據(jù)傳遞需要借助操作系統(tǒng)提供特殊的方法,如:文件、管道、信號(hào)、共享內(nèi)存、消息隊(duì)列、套接字、命名管道等。隨著計(jì)算機(jī)的蓬勃發(fā)展,一些方法由于自身設(shè)計(jì)缺陷被淘汰或者棄用?,F(xiàn)今常用的進(jìn)程間通信方式有:
1)管道 (使用最簡(jiǎn)單)
2)信號(hào) (開銷最小)
3)共享映射區(qū) (無血緣關(guān)系)
4)本地套接字 (最穩(wěn)定)
三、進(jìn)程間通信方法介紹
1. 管道
(1)管道的概念:
管道是一種最基本的IPC機(jī)制,作用于有血緣關(guān)系的進(jìn)程之間,完成數(shù)據(jù)傳遞。調(diào)用pipe系統(tǒng)函數(shù)即可創(chuàng)建一個(gè)管道。有如下特質(zhì):
1) 其本質(zhì)是一個(gè)偽文件(實(shí)為內(nèi)核緩沖區(qū))
2)由兩個(gè)文件描述符引用,一個(gè)表示讀端,一個(gè)表示寫端。
3) 規(guī)定數(shù)據(jù)從管道的寫端流入管道,從讀端流出。
管道的原理: 管道實(shí)為內(nèi)核使用環(huán)形隊(duì)列機(jī)制,借助內(nèi)核緩沖區(qū)(4k)實(shí)現(xiàn)。
管道的局限性:
1) 數(shù)據(jù)一旦被讀走,便不在管道中存在,不可反復(fù)讀取。
2) 由于管道采用半雙工通信方式。因此,數(shù)據(jù)只能在一個(gè)方向上流動(dòng)。
3) 只能在有公共祖先的進(jìn)程間使用管道。
常見的通信方式有,單工通信、半雙工通信、全雙工通信。
(2)管道相關(guān)函數(shù)
創(chuàng)建管道
int pipe(int pipefd[2]);?????????????? 成功:0;失?。?1,設(shè)置errno
函數(shù)調(diào)用成功返回r/w兩個(gè)文件描述符。無需open,但需手動(dòng)close。規(guī)定:fd[0] → r; fd[1] → w,就像0對(duì)應(yīng)標(biāo)準(zhǔn)輸入,1對(duì)應(yīng)標(biāo)準(zhǔn)輸出一樣。向管道文件讀寫數(shù)據(jù)其實(shí)是在讀寫內(nèi)核緩沖區(qū)。
管道創(chuàng)建成功以后,創(chuàng)建該管道的進(jìn)程(父進(jìn)程)同時(shí)掌握著管道的讀端和寫端。如何實(shí)現(xiàn)父子進(jìn)程間通信呢?通常可以采用如下步驟:
1)父進(jìn)程調(diào)用pipe函數(shù)創(chuàng)建管道,得到兩個(gè)文件描述符fd[0]、fd[1]指向管道的讀端和寫端。
2)父進(jìn)程調(diào)用fork創(chuàng)建子進(jìn)程,那么子進(jìn)程也有兩個(gè)文件描述符指向同一管道。
3)父進(jìn)程關(guān)閉管道讀端,子進(jìn)程關(guān)閉管道寫端。父進(jìn)程可以向管道中寫入數(shù)據(jù),子進(jìn)程將管道中的數(shù)據(jù)讀出。由于管道是利用環(huán)形隊(duì)列實(shí)現(xiàn)的,數(shù)據(jù)從寫端流入管道,從讀端流出,這樣就實(shí)現(xiàn)了進(jìn)程間通信。
練習(xí):父子進(jìn)程使用管道通信,父寫入字符串,子進(jìn)程讀出并打印到屏幕?
父進(jìn)程寫子進(jìn)程讀
1 #include 2 #include 3 #include 4 5 int main() 6 { 7 int fd[2]; 8 pipe(fd); 9 pid_t pid = fork(); 10 11 if (pid == 0) 12 { 13 //子進(jìn)程關(guān)閉寫端 14 close(fd[1]); 15 char buf[256] = {0}; 16 while(1) 17 { 18 memset(buf, 0, sizeof(buf)); 19 int ret = read(fd[0], buf, sizeof(buf)); 20 if (ret == 0) 21 { 22 printf("read over!\n"); 23 break; 24 } 25 else if(ret > 0) 26 { 27 write(STDOUT_FILENO,buf,ret); 28 } 29 } 30 } 31 else if (pid > 0) 32 { 33 //父進(jìn)程關(guān)閉讀端 34 close(fd[0]); 35 char buf[256] = {0}; 36 int num = 0; 37 while(1) 38 { 39 memset(buf, 0, sizeof(buf)); 40 sprintf(buf, "data from parent %d\n", num++); 41 write(fd[1], buf, sizeof(buf)); 42 sleep(1); 43 } 44 } 45 46 return 0; 47 }
(3)管道的讀寫行為
使用管道需要注意以下4種特殊情況(假設(shè)都是阻塞I/O操作,沒有設(shè)置O_NONBLOCK標(biāo)志):
1)如果所有指向管道寫端的文件描述符都關(guān)閉了(管道寫端引用計(jì)數(shù)為0),而仍然有進(jìn)程從管道的讀端讀數(shù)據(jù),那么管道中剩余的數(shù)據(jù)都被讀取后,再次read會(huì)返回0,就像讀到文件末尾一樣。
2)?如果有指向管道寫端的文件描述符沒關(guān)閉(管道寫端引用計(jì)數(shù)大于0),而持有管道寫端的進(jìn)程也沒有向管道中寫數(shù)據(jù),這時(shí)有進(jìn)程從管道讀端讀數(shù)據(jù),那么管道中剩余的數(shù)據(jù)都被讀取后,再次read會(huì)阻塞,直到管道中有數(shù)據(jù)可讀了才讀取數(shù)據(jù)并返回。
3)如果所有指向管道讀端的文件描述符都關(guān)閉了(管道讀端引用計(jì)數(shù)為0),這時(shí)有進(jìn)程向管道的寫端write,那么該進(jìn)程會(huì)收到信號(hào)SIGPIPE,通常會(huì)導(dǎo)致進(jìn)程異常終止。當(dāng)然也可以對(duì)SIGPIPE信號(hào)實(shí)施捕捉,不終止進(jìn)程。具體方法信號(hào)章節(jié)詳細(xì)介紹。
4)如果有指向管道讀端的文件描述符沒關(guān)閉(管道讀端引用計(jì)數(shù)大于0),而持有管道讀端的進(jìn)程也沒有從管道中讀數(shù)據(jù),這時(shí)有進(jìn)程向管道寫端寫數(shù)據(jù),那么在管道被寫滿時(shí)再次write會(huì)阻塞,直到管道中有空位置了才寫入數(shù)據(jù)并返回。
總結(jié):
1)讀管道:? 1. 管道中有數(shù)據(jù),read返回實(shí)際讀到的字節(jié)數(shù)。
2. 管道中無數(shù)據(jù):
(1) 管道寫端被全部關(guān)閉,read返回0 (好像讀到文件結(jié)尾)
(2) 寫端沒有全部被關(guān)閉,read阻塞等待(不久的將來可能有數(shù)據(jù)遞達(dá),此時(shí)會(huì)讓出cpu)
2)寫管道:? 1. 管道讀端全部被關(guān)閉, 進(jìn)程異常終止(也可使用捕捉SIGPIPE信號(hào),使進(jìn)程不終止)
2. 管道讀端沒有全部關(guān)閉:
(1) 管道已滿,write阻塞。
(2) 管道未滿,write將數(shù)據(jù)寫入,并返回實(shí)際寫入的字節(jié)數(shù)。
練習(xí)1:使用管道實(shí)現(xiàn)父子進(jìn)程間通信,完成:ls | wc -l。假定父進(jìn)程實(shí)現(xiàn)ls,子進(jìn)程實(shí)現(xiàn)wc?
注意:ls命令正常會(huì)將結(jié)果集寫出到stdout,但現(xiàn)在會(huì)寫入管道的寫端;wc -l 正常應(yīng)該從stdin讀取數(shù)據(jù),但此時(shí)會(huì)從管道的讀端讀。
實(shí)現(xiàn)父進(jìn)程ls 子進(jìn)程wc -l
1 #include 2 #include 3 4 int main() 5 { 6 int fd[2]; 7 pipe(fd); 8 9 pid_t pid = fork(); 10 if(pid == 0){ 11 //son 12 //son -- > ls 13 //關(guān)閉 寫端 14 close(fd[1]); 15 //1. 先重定向 16 dup2(fd[0], STDIN_FILENO);//標(biāo)準(zhǔn)輸入重定向到管道寫端 17 //2. execlp 18 execlp("wc","wc","-l",NULL); 19 }else if(pid > 0){ 20 //parent 21 //關(guān)閉讀端 22 close(fd[0]); 23 //1. 先重定向,標(biāo)準(zhǔn)輸出重定向到管道讀端 24 dup2(fd[1], STDOUT_FILENO); 25 //2. execlp 26 execlp("ls","ls",NULL); 27 } 28 29 return 0; 30 }
父子進(jìn)程實(shí)現(xiàn)ps aux | grep bash
1 #include 2 #include 3 4 int main() 5 { 6 int fd[2]; 7 pipe(fd); 8 9 pid_t pid = fork(); 10 if(pid == 0){ 11 //son 12 //son -- > ps 13 //關(guān)閉 讀端 14 close(fd[0]); 15 //1. 先重定向 16 dup2(fd[1],STDOUT_FILENO);//標(biāo)準(zhǔn)輸出重定向到管道寫端 17 //2. execlp 18 execlp("ps","ps","aux",NULL); 19 }else if(pid > 0){ 20 //parent 21 //關(guān)閉寫端 22 close(fd[1]); 23 //1. 先重定向,標(biāo)準(zhǔn)輸入重定向到管道讀端 24 dup2(fd[0],STDIN_FILENO); 25 //2. execlp 26 execlp("grep","grep","bash",NULL); 27 } 28 29 return 0; 30 }
執(zhí)行結(jié)果分析:程序執(zhí)行,發(fā)現(xiàn)程序執(zhí)行結(jié)束,shell還在阻塞等待用戶輸入。這是因?yàn)?,shell → fork → ./pipe2, 程序pipe2的子進(jìn)程將stdin重定向給管道,父進(jìn)程執(zhí)行的ls會(huì)將結(jié)果集通過管道寫給子進(jìn)程。若父進(jìn)程在子進(jìn)程打印wc的結(jié)果到屏幕之前被shell調(diào)用wait回收,shell就會(huì)先輸出$提示符。
練習(xí)2:使用管道實(shí)現(xiàn)兄弟進(jìn)程間通信。 兄:ls? 弟: wc -l? 父:等待回收子進(jìn)程?要求,使用“循環(huán)創(chuàng)建N個(gè)子進(jìn)程”模型創(chuàng)建兄弟進(jìn)程,使用循環(huán)因子i標(biāo)示。注意管道讀寫行為。
實(shí)現(xiàn)思路:父進(jìn)程關(guān)閉讀寫端,兩個(gè)子進(jìn)程,一個(gè)關(guān)閉管道的讀端去寫,一個(gè)關(guān)閉管道的寫端去讀。
兄弟進(jìn)程間實(shí)現(xiàn)ls | wc -l
1 #include 2 #include 3 4 int main() 5 { 6 int fd[2]; 7 pid_t pid; 8 int n = 2, i = 0; 9 pipe(fd); 10 11 for (i = 0; i < n; i++) 12 { 13 pid = fork(); 14 if (pid == 0) 15 { 16 break; 17 } 18 } 19 20 //兄弟進(jìn)程 21 if (i == 0) 22 { 23 printf("Brother1 pid = %d, ppid = %d\n", getpid(), getppid()); 24 //1. 關(guān)閉寫端 25 close(fd[1]); 26 //2. 先重定向 27 dup2(fd[0], STDIN_FILENO);//標(biāo)準(zhǔn)輸入重定向到管道寫端 28 //3. 執(zhí)行execlp 29 execlp("wc","wc","-l",NULL); 30 31 } 32 //兄弟進(jìn)程 33 else if (i == 1) 34 { 35 printf("Brother2 pid = %d, ppid = %d\n", getpid(), getppid()); 36 //1. 關(guān)閉讀端 37 close(fd[0]); 38 //2. 先重定向,標(biāo)準(zhǔn)輸出重定向到管道讀端 39 dup2(fd[1], STDOUT_FILENO); 40 //3. execlp 41 execlp("ls","ls",NULL); 42 43 } 44 45 else if (i == 2) 46 { 47 //parent 48 //父親需要關(guān)閉讀寫兩端 49 close(fd[0]); 50 close(fd[1]); 51 //回收子進(jìn)程 52 wait(NULL); 53 wait(NULL); 54 } 55 56 return 0; 57 }
兄弟進(jìn)程實(shí)現(xiàn)ps aux | grep bash
1 #include 2 #include 3 #include 4 #include 5 6 int main() 7 { 8 int fd[2]; 9 pipe(fd); 10 pid_t pid; 11 int n =2,i = 0; 12 for(i = 0; i < n; i ++){ 13 pid = fork(); 14 if(pid == 0){ 15 break; 16 } 17 } 18 19 //i = 0 ,代表兄長(zhǎng),1 - 代表弟弟,2- 父親 20 if(i == 0){ 21 //兄長(zhǎng)進(jìn)程 22 //1. 關(guān)閉讀端 23 close(fd[0]); 24 //2. 重定向 25 dup2(fd[1],STDOUT_FILENO); 26 //3. 執(zhí)行 execlp 27 execlp("ps","ps","aux",NULL); 28 29 }else if(i == 1){ 30 //弟弟 31 //1. 關(guān)閉寫端 32 close(fd[1]); 33 //2. 重定向 34 dup2(fd[0],STDIN_FILENO); 35 //3. 執(zhí)行ececlp 36 execlp("grep","grep","bash",NULL); 37 38 }else if(i == 2){ 39 //parent 40 //父親需要關(guān)閉讀寫兩端 41 close(fd[0]); 42 close(fd[1]); 43 //回收子進(jìn)程 44 wait(NULL); 45 wait(NULL); 46 } 47 48 49 return 0; 50 }
測(cè)試:是否允許,一個(gè)pipe有一個(gè)寫端多個(gè)讀端呢?是否允許有一個(gè)讀端多個(gè)寫端呢?
一寫多讀
1 #include 2 #include 3 #include 4 5 int main() 6 { 7 int fd[2]; 8 pid_t pid; 9 int n = 3, i = 0; 10 pipe(fd); 11 12 for (i = 0; i < n; i++) 13 { 14 pid = fork(); 15 if (pid == 0) 16 { 17 break; 18 } 19 } 20 21 //兄弟進(jìn)程 22 if (i == 0) 23 { 24 printf("Brother1 pid = %d, ppid = %d\n", getpid(), getppid()); 25 //1. 關(guān)閉寫端 26 close(fd[1]); 27 //2. 先重定向 28 dup2(fd[0], STDIN_FILENO);//標(biāo)準(zhǔn)輸入重定向到管道寫讀端 29 //3. 執(zhí)行execlp 30 char buf[256] = {0}; 31 while(1) 32 { 33 memset(buf, 0, sizeof(buf)); 34 int ret = read(fd[0], buf, sizeof(buf)); 35 if (ret == 0) 36 { 37 printf("read over"); 38 break; 39 } 40 } 41 } 42 43 //兄弟進(jìn)程 44 else if (i == 1) 45 { 46 printf("Brother2 pid = %d, ppid = %d\n", getpid(), getppid()); 47 //1. 關(guān)閉讀端 48 close(fd[1]); 49 //2. 先重定向,標(biāo)準(zhǔn)輸出重定向到管道讀端 50 dup2(fd[0], STDIN_FILENO); 51 char buf[256] = {0}; 52 while(1) 53 { 54 memset(buf, 0, sizeof(buf)); 55 int ret = read(fd[0], buf, sizeof(buf)); 56 if (ret == 0) 57 { 58 printf("read over"); 59 break; 60 } 61 } 62 } 63 //兄弟進(jìn)程 64 else if (i == 2) 65 { 66 printf("Brother3 pid = %d, ppid = %d\n", getpid(), getppid()); 67 //1. 關(guān)閉讀端 68 close(fd[0]); 69 //2. 先重定向,標(biāo)準(zhǔn)輸出重定向到管道讀端 70 dup2(fd[1], STDOUT_FILENO); 71 //3. 寫數(shù)據(jù)到寫端 72 int num = 0; 73 char buf[256] = {0}; 74 while(1) 75 { 76 memset(buf, 0, sizeof(buf)); 77 sprintf(buf, "from broth3 %d\n", num++); 78 int ret = write(fd[1], buf, sizeof(buf)); 79 if (ret == -1) 80 { 81 perror("write err:"); 82 break; 83 } 84 sleep(1); 85 } 86 } 87 else if (i == 3) 88 { 89 //parent 90 //父親需要關(guān)閉讀寫兩端 91 close(fd[0]); 92 close(fd[1]); 93 //回收子進(jìn)程 94 wait(NULL); 95 wait(NULL); 96 wait(NULL); 97 } 98 99 return 0; 100 }
結(jié)論:一個(gè)讀多個(gè)寫會(huì)hang住。

多寫一讀
1 #include 2 #include 3 #include 4 5 int main() 6 { 7 int fd[2]; 8 pid_t pid; 9 int n = 3, i = 0; 10 pipe(fd); 11 12 for (i = 0; i < n; i++) 13 { 14 pid = fork(); 15 if (pid == 0) 16 { 17 break; 18 } 19 } 20 21 //兄弟進(jìn)程 22 if (i == 0) 23 { 24 printf("Brother1 pid = %d, ppid = %d\n", getpid(), getppid()); 25 //1. 關(guān)閉寫端 26 close(fd[1]); 27 //2. 先重定向 28 dup2(fd[0], STDIN_FILENO);//標(biāo)準(zhǔn)輸入重定向到管道寫讀端 29 //3. 執(zhí)行execlp 30 char buf[256] = {0}; 31 while(1) 32 { 33 memset(buf, 0, sizeof(buf)); 34 int ret = read(fd[0], buf, sizeof(buf)); 35 if (ret == 0) 36 { 37 printf("read over"); 38 break; 39 } 40 } 41 } 42 //兄弟進(jìn)程 43 else if (i == 1) 44 { 45 printf("Brother2 pid = %d, ppid = %d\n", getpid(), getppid()); 46 //1. 關(guān)閉讀端 47 close(fd[0]); 48 //2. 先重定向,標(biāo)準(zhǔn)輸出重定向到管道讀端 49 dup2(fd[1], STDOUT_FILENO); 50 int num = 0; 51 char buf[256] = {0}; 52 while(1) 53 { 54 memset(buf, 0, sizeof(buf)); 55 sprintf(buf, "from broth2 %d\n", num++); 56 int ret = write(fd[1], buf, sizeof(buf)); 57 if (ret == -1) 58 { 59 perror("write err:"); 60 break; 61 } 62 sleep(1); 63 } 64 } 65 //兄弟進(jìn)程 66 else if (i == 2) 67 { 68 printf("Brother3 pid = %d, ppid = %d\n", getpid(), getppid()); 69 //1. 關(guān)閉讀端 70 close(fd[0]); 71 //2. 先重定向,標(biāo)準(zhǔn)輸出重定向到管道讀端 72 dup2(fd[1], STDOUT_FILENO); 73 //3. 寫數(shù)據(jù)到寫端 74 int num = 0; 75 char buf[256] = {0}; 76 while(1) 77 { 78 memset(buf, 0, sizeof(buf)); 79 sprintf(buf, "from broth3 %d\n", num++); 80 int ret = write(fd[1], buf, sizeof(buf)); 81 if (ret == -1) 82 { 83 perror("write err:"); 84 break; 85 } 86 sleep(1); 87 } 88 } 89 else if (i == 3) 90 { 91 //parent 92 //父親需要關(guān)閉讀寫兩端 93 close(fd[0]); 94 close(fd[1]); 95 //回收子進(jìn)程 96 wait(NULL); 97 wait(NULL); 98 wait(NULL); 99 } 100 101 return 0; 102 }
結(jié)論:一個(gè)寫多個(gè)讀會(huì)hang住。
(4)管道緩沖區(qū)大小
可以使用ulimit -a 命令來查看當(dāng)前系統(tǒng)中創(chuàng)建管道文件所對(duì)應(yīng)的內(nèi)核緩沖區(qū)大小。通常為:
pipe size (512 bytes, -p) 8
也可以使用fpathconf函數(shù),借助參數(shù)??????? 選項(xiàng)來查看。使用該宏應(yīng)引入頭文件
long fpathconf(int fd, int name);????? 成功:返回管道的大小???????? 失?。?1,設(shè)置errno
(5)管道優(yōu)劣
優(yōu)點(diǎn):簡(jiǎn)單,相比信號(hào),套接字實(shí)現(xiàn)進(jìn)程間通信,簡(jiǎn)單很多。
缺點(diǎn):1. 只能單向通信,雙向通信需建立兩個(gè)管道。
2. 只能用于父子、兄弟進(jìn)程(有共同祖先)間通信。該問題后來使用fifo有名管道解決。
2. FIFO
FIFO常被稱為有名管道,以區(qū)分管道(pipe)。管道(pipe)只能用于“有血緣關(guān)系”的進(jìn)程間。但通過FIFO,不相關(guān)的進(jìn)程也能交換數(shù)據(jù)。
FIFO是Linux基礎(chǔ)文件類型中的一種。但FIFO文件在磁盤上沒有數(shù)據(jù)塊,僅僅用來標(biāo)識(shí)內(nèi)核中一條通道。各進(jìn)程可以打開這個(gè)文件進(jìn)行read/write,實(shí)際上是在讀寫內(nèi)核通道,這樣就實(shí)現(xiàn)了進(jìn)程間通信。
創(chuàng)建方式:
1. 命令:mkfifo 管道名
2. 庫(kù)函數(shù):int mkfifo(const char *pathname, ?mode_t mode);? 成功:0; 失?。?1
一旦使用mkfifo創(chuàng)建了一個(gè)FIFO,就可以使用open打開它,常見的文件I/O函數(shù)都可用于fifo。如:close、read、write、unlink等。
fifo_w.c
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 9 int main(int argc,char * argv[]) 10 { 11 if(argc != 2){ 12 printf("./a.out fifoname\n"); 13 return -1; 14 } 15 16 int ret = mkfifo(argv[1], 0666); 17 if (ret < 0 && errno != EEXIST) 18 { 19 printf("create fifo file %s failed\n", argv[1]); 20 return -1; 21 } 22 23 // 創(chuàng)建一個(gè) myfifo 文件 24 //打開fifo文件 25 printf("begin open ....\n"); 26 int fd = open(argv[1],O_WRONLY); 27 printf("end open ....\n"); 28 //寫 29 char buf[256]; 30 int num = 1; 31 while(1){ 32 memset(buf,0x00,sizeof(buf)); 33 sprintf(buf,"from write data:%04d",num++); 34 write(fd,buf,strlen(buf)); 35 sleep(1); 36 //循環(huán)寫 37 } 38 //關(guān)閉描述符 39 close(fd); 40 return 0; 41 }
fifo_r.c
1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 8 int main(int argc,char *argv[]) 9 { 10 if(argc != 2){ 11 printf("./a.out fifoname\n"); 12 return -1; 13 } 14 printf("begin oepn read...\n"); 15 int fd = open(argv[1],O_RDONLY); 16 printf("end oepn read...\n"); 17 18 char buf[256]; 19 int ret; 20 while(1){ 21 //循環(huán)讀 22 memset(buf,0x00,sizeof(buf)); 23 ret = read(fd,buf,sizeof(buf)); 24 if(ret > 0){ 25 printf("read:%s\n",buf); 26 } 27 } 28 29 close(fd); 30 return 0; 31 }
注意:
FIFOs
Opening the read or write end of a FIFO blocks until the other end is also opened (by another process or thread). See fifo(7) for further details.
open注意事項(xiàng),打開fifo文件的時(shí)候,read端會(huì)阻塞等待write端open,write端同理,也會(huì)阻塞等待另外一端打開。
【Linux C編程】第十一章 進(jìn)程間通信2
Linux 任務(wù)調(diào)度
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。