Linux C編程第十一章 進(jìn)程間通信1

      網(wǎng)友投稿 827 2025-03-31

      一、整體大綱


      二、進(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住。

      【Linux C編程】第十一章 進(jìn)程間通信1

      多寫一讀

      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)容。

      上一篇:Word2007表格技巧:靈活調(diào)整表格列寬
      下一篇:Minifs函數(shù)(minifs函數(shù)在2003里能不能實(shí)現(xiàn))
      相關(guān)文章
      亚洲一级特黄大片无码毛片| 亚洲精品无码日韩国产不卡av| 精品久久久久亚洲| 色偷偷亚洲女人天堂观看欧| 久久综合亚洲色一区二区三区| 亚洲av无码乱码国产精品fc2| 亚洲人JIZZ日本人| 亚洲黄黄黄网站在线观看| 一级毛片直播亚洲| 老司机亚洲精品影院在线观看| 亚洲精品久久无码| 亚洲国产精品18久久久久久| 久久亚洲中文字幕无码| 亚洲aⅴ无码专区在线观看| 亚洲爆乳无码精品AAA片蜜桃| 亚洲人成色777777精品| 99亚洲乱人伦aⅴ精品| 国产成人 亚洲欧洲| 亚洲第一区精品观看| 亚洲国产一区二区三区| 久久影院亚洲一区| 亚洲处破女AV日韩精品| 亚洲精选在线观看| 亚洲精品在线视频观看| 亚洲一区二区三区深夜天堂| 亚洲国产成人精品无码一区二区 | 亚洲AV无一区二区三区久久| 亚洲成亚洲乱码一二三四区软件| 亚洲av日韩综合一区在线观看| 久久久久亚洲AV成人无码网站| 亚洲人成网www| 亚洲最大中文字幕| 亚洲熟妇无码一区二区三区| 亚洲国产精品嫩草影院| 亚洲福利在线播放| 亚洲日本乱码在线观看| 91亚洲一区二区在线观看不卡 | 精品亚洲成AV人在线观看| 亚洲国产精品久久丫| 亚洲乱妇熟女爽到高潮的片| 日韩欧美亚洲中文乱码|