管道之 協同程序

2021-08-14 09:46:35 字數 2968 閱讀 9152

協同程序:

參考:

在shell 管道中,當乙個程式產生乙個過濾器的輸入,又讀取這個過濾器的輸出,則此種過濾程式叫做協同程序.

協同程序通常在shell的後台執行,其標準輸入和標準輸出通過管道連線到另乙個程式。

popen 與協同程序的區別:

popen只提供連線到另乙個程序的標準輸入或標準輸出的乙個單向管道;

協同程序,連線到另乙個程序的兩個單向管道:乙個接到其標準輸入,另乙個則來自其標準輸出;

協同程序演示: 建立兩個管道, 乙個是協同程序的標準輸入,另乙個是協同程序的標準輸出,將資料寫到其標準輸入,經其處理後,再從其標準輸出讀取資料。

協同程序演示: 建立兩個管道, 乙個是協同程序的標準輸入,另乙個是協同程序的標準輸出,將資料寫到其標準輸入,經其處理後,再從其標準輸出讀取資料。

第一步, 建立兩個管道,fd1[2]和fd2[2](父程序在fd1[1]寫入資料,再從fd2[0]讀出資料)。

第二步, 呼叫fork()建立子程序。

第三步, 在子程序中,關閉fd1[1], fd2[0],並呼叫dup2使協同程序的標準輸入連線到fd1[0], 標準輸出連線到fd2[1],這樣就將兩個管道連線起來了。

再在子程序中呼叫execl呼叫編寫的協同處理程式(這裡的協同程式做為一般的程式編寫即可,從標準輸入讀入資料,處理後輸出到標準輸出)。

第四步, 在父程序中,關閉fd1[0], fd2[1],將協同程序需要處理的資料寫入fd1[1], 再從fd2[0]讀出協同程序的輸出即可。

程式清單15-8 對兩個數求和的簡單過濾程式:乙個簡單的協同程序,它從其標準輸入讀兩個數,計算它們的和,然後將結果寫至標準輸出。

#include "apue.h"

int main(void)

else

}exit(0);

}

對此程式進行編譯,將其可執行目標**存入名為add2的檔案。

程式清單15-9從其標準輸入讀入兩個數之後呼叫add2協同程序,並將協同程序送來的值寫到其標準輸出。

程式清單15-9 驅動add2過濾程式的程式

#include "apue.h"

static

void sig_pipe(int); /* our signal handler */

int main(void)

else

if(pid > 0) /* parent */

if((n = read(fd2[0], line, maxline)) < 0) err_sys("read error from pipe");

if(n == 0)

line[n] = 0; /* null terminate */

if(fputs(line, stdout) == eof) err_sys("fputs error");

}if(ferror(stdin)) err_sys("fgets error on stdin");

exit(0);

}else

/* child */

if(fd2[1] != stdout_fileno)

if(execl("./add2", "add2", (char *)0) < 0) err_sys("execl error");

}exit(0);

}static

void sig_pipe(int signo)

在程式中建立了兩個管道,父、子程序各自關閉它們不需要使用的埠。兩個管道乙個用作協同程序的標準輸入,另乙個則用作它的標準輸出。子程序呼叫dup2使管道描述符移至其標準輸入和標準輸出,然後呼叫execl.

父程序write 資料並最終到大 add的輸入端: 父寫資料到管道1的fd1[1] 端, 子程序通過dup2將stdin指向fd1[0],從而讀取父程序寫入的資料並進行處理。

父程序讀出資料: 父進製從管道2的fd2[0]中讀取資料,子程序通過dup2將stout指向fd2[1]中,所有add處理後的資料在管道2中,父程序可以讀到。

apue2上闡述的產生死鎖的條件:

但是書上描述的產生死鎖的條件其實是錯誤的,為什麼這麼說呢?

fgets從標準輸入讀取並不會發生阻塞,因為父程序確確實實將資料寫入管道了。add2計算兩數之和後呼叫printf寫入結果,問題就出在這了 – 因為操作管道的標準i/o使用的是全緩衝,所以printf之後stdio緩衝區並沒有滿,資料依然停留在stdio緩衝區,並未寫入管道,這就導致父程序的read會一直阻塞,而子程序接下來的fgets也會一直阻塞,這才是產生死鎖的真正條件!(管道+標準i/o—->全緩衝 ????????)

那麼什麼時候會出現書上描述的死鎖情況呢 – 很簡單,只有在父程序也是使用的標準i/o的情況下才會出現,這樣子程序fgets讀取不到資料而阻塞。

因此,除了書上提到的使用setvbuf改變緩衝型別為行緩衝的方法外,還可以在子程序的兩個printf之後顯示地呼叫fflush(stdout),這樣也是可以解決問題的。

下面是有修改add2.c程式執行後:

#include "apue.h"

int main(void)

exit(0);

}

執行: 執行pip4出現死鎖, 因為fgets 是管道,是全緩衝,行快取,

}執行:

協同程序 管道實現

15.4 協同程序 1 概念 過濾程式 指從標準輸入中讀取資料,向標準輸出寫資料的程式 比如管道產生兩個程式 協同程序 某個過濾程式1既能產生過濾程式2的輸入,又能讀取讀取過濾程式2的輸出時,過濾程式1就為協同程序 coprocess 注 1.管道就是協同程序的例子。2.當子程序為過濾程式時,父程序...

程序間通訊之協同程序

unix系統過濾程式從標準輸入讀取資料,對其進行適當處理後寫到標準輸出。幾個過濾程式通常在shell管道命令列中線性地連線。當乙個程式產生某個過濾程式的輸入,同時又讀取該過濾程式的輸出時,則該過濾程式就成為協同程序 coprocess korn shell提供了協同程序。bourne shell b...

協同程序實現生產者消費者

及注釋如下,使用print函式列印值和行號,可以看到 的執行路徑 resume協程,如果協程執行的過程中呼叫yield函式,則resume函式返回yield的引數 function receive prod local status,value coroutine.resume prod print...