程序間通訊之協同程序

2021-09-08 17:07:22 字數 2913 閱讀 1362

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

korn shell提供了協同程序。bourne shell、bourne-again shell和c shell並沒有提供按協同程序方式將程序連線起來的方法。協同程序通常在shell的後台執行,其標準輸入和標準輸出通過管道連線到另乙個程式。

popen只提供連線到另乙個程序的標準輸入或標準輸出的乙個單向管道,而對於協同程序,則它有連線到另乙個程序的兩個單向管道——乙個接到其標準輸入,另乙個則來自其標準輸出。我們先要將資料寫到其標準輸入,經其處理後,再從其標準輸出讀取資料。

例項

程序線建立兩個管道:乙個是協同程序的標準輸入,另乙個是協同程序的標準輸出。圖15-8顯示了這種安排。

圖15-8 寫協同程序的標準輸入,讀它的標準輸出

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

程式清單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(

intsigno)

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

例項

在協同程序add2中,有意地使用了read和writei/o(unix系統呼叫)。如果使用標準i/o改寫該協同程序,其後果是什麼呢?程式清單15-10為改寫後的版本。

程式清單15-10 對兩個數求和的過濾程式,使用標準i/o

#include "

apue.h

"int

main(

void

)

else

}exit(0);

}

若程式清單15-9呼叫此新的協同程序,則它不再工作。問題出在系統預設的標準i/o緩衝機制上(見當呼叫程式清單15-10所示程式時,對標準輸入的第乙個fgets引起標準i/o庫分配乙個緩衝區,並選擇緩衝區的型別。因為標準輸入是個管道,所以標準i/o庫由系統預設是全緩衝的。對標準輸出也做同樣的處理。當add2從其標準輸入讀取而發生阻塞時,程式清單15-9程式從管道讀時也發生阻塞,於是產生了死鎖。

為此,更改將要執行的協同程序的緩衝型別,在程式清單15-10中的while迴圈之前加上下面4行:

if(setvbuf(stdin, null, _iolbf, 0) != 0

) err_sys(

"setvbuf error");

if(setvbuf(stdout, null, _iolbf, 0) != 0

) err_sys(

"setvbuf error

");

這些**行使得當有一行可用時,fgets就返回,並使得當輸出一換行符時,printf立即執行fflush操作。

本篇博文內容摘自《unix環境高階程式設計》(第二版),僅作個人學習記錄所用。關於本書可參考:

管道之 協同程序

協同程序 參考 在shell 管道中,當乙個程式產生乙個過濾器的輸入,又讀取這個過濾器的輸出,則此種過濾程式叫做協同程序.協同程序通常在shell的後台執行,其標準輸入和標準輸出通過管道連線到另乙個程式。popen 與協同程序的區別 popen只提供連線到另乙個程序的標準輸入或標準輸出的乙個單向管道...

協同程序 管道實現

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

程序管理之程序間通訊

四 訊息佇列 message queue 五 共享記憶體 shared memory 六 套接字 socket 程序作為人類的發明,自然也免不了脫離人類的習性,也有通訊的需求。如果程序之間不進行任何通訊,那麼程序所能完成的任務就要大打折扣。人類的通訊方式無外乎對白 通過聲音溝通 打手勢 寫信 發電報...