2009年12月12日 星期六

Pipe

當兩個不同的Process要溝通時,我們可以用pipe來達成。簡單來說,pipe就像是一條水管,連接兩個Process,其中一端寫入資料到水管,另一端便可從水管中讀出此資料。

建立pipe:
#include <unistd.h>
int pipe(int pipefd[2]);

呼叫pipe()來建立pipe,其參數int pipefd[2]是用來回傳兩個file descriptors,pipefd[0]代表的是pipe的讀取端,pipefd[1]則是pipe的寫入端。

簡單範例:
#include <stdio.h>
#include <string.h>

int main() {
int pipefd[2];
pipe(pipefd);

char writeBuf[] = "Hello pipe!";
write(pipefd[1], writeBuf, strlen(writeBuf));

char readBuf[20];
int n = read(pipefd[0], readBuf, 20);
readBuf[n] = 0;
printf("%s\n", readBuf);

return 0;
}

接下來就將單一Process擴展到不同的Process,寫出ls | wc -l,也就是計算當前目錄下有幾個檔案。
先利用fork產生Child Process,再叫用execlp()執行外部指令。

#include <stdio.h>
#include <unistd.h>

int main() {
int pipefd[2];
pipe(pipefd);

pid_t pid = fork();
if(pid != 0) {
close(pipefd[1]);
dup2(pipefd[0], 0);
close(pipefd[0]);
execlp("wc", "wc", "-l", NULL);
}
else {
close(pipefd[0]);
dup2(pipefd[1], 1);
close(pipefd[1]);

execlp("ls", "ls", NULL);
}
return 0;
}

由於fork會使pipefd[0], pipefd[1]產生兩份,記得把不必要的Descriptor關閉,可避免不當的操作。
比較需要注意的便是dup2()的用法,dup2(pipefd[0], 0)可以把它想成複製pipefd[0]且當作是標準輸入(stdin),如此wc -l從stdin讀資料就會從pipe中讀取。
可參考此網頁的說明,便能明白dup2()的用意。

沒有留言:

張貼留言