fork()、pipe()、dup2() 和 execlp() 的組合技法
對一般程式來說,管線(pipe)機制很少會用到,尤其對於在 Windows 底下的程式開發者來說,很可能前所未聞,而在 Unix-like 環境中常見的例子,就是往往在命令後面加上『|』,其意味使用『管子(pipe)』將內容導入另一個程式裡,如:『dmesg | grep ALSA』。在該例中,Shell 有趣的將 demsg 標準輸出(standard output)全數導入 grep 程式的標準輸入(standard input)中,再交由 grep 處理並找出存在 ALSA 字串的句子所在。
另一個情況,Web Server 在支援 CGI 時,也會使用到 pipe。這是最典型的例子,當 Web Server 欲執行一支外部 CGI Program 時,會利用 pipe 去模擬該 CGI 的標準輸入及輸出(Standard I/O)。以上說明當然只是大致上的做法,細節還需加上 fork() 和 dup2() 的配合,透過個範例可清楚瞭解這部份的實作。
這是一個簡單的範例:
此範例相當易懂,不外乎是使用 fork() 建立一個新的 Process,再去執行一支外部 CGI,而主程式會等待外部 CGI 的輸出,再用 printf() 印出來 CGI 的輸出內容。而比較令人騷不著頭緒的部份,就是 pipe() 和 dup2() 的關係,使用 pipe() 可建立一組雙向的管線,範例中是一組有兩個整數值的陣列 pfd,這是一條水管,從 pfd[0] 進入的東西會從 pfd[1] 出來,反之亦然,除此之外,它也是可以跨 Process,達成兩個程式溝通的目的。除了建立 pipe,接著利用 dup2(),可以讓管線去取代外部程式的標準輸出(standard output),然後讓主程式用管線接收。
註:pipe() 回傳的是兩個檔案描述編號(file discriptions),需要用相應的檔案函數去操控它。
另一個情況,Web Server 在支援 CGI 時,也會使用到 pipe。這是最典型的例子,當 Web Server 欲執行一支外部 CGI Program 時,會利用 pipe 去模擬該 CGI 的標準輸入及輸出(Standard I/O)。以上說明當然只是大致上的做法,細節還需加上 fork() 和 dup2() 的配合,透過個範例可清楚瞭解這部份的實作。
這是一個簡單的範例:
void cgi_run(const char* filename) { char buffer[1024] = { 0 }; int len; int pfd[2]; int status; pid_t pid; /* create pipe */ if (pipe(pfd)<0) return -1; /* fork to execute external program or scripts */ pid = fork(); if (pid<0) { return 0; } else if (pid==0) { /* child process */ dup2(pfd[1], STDOUT_FILENO); close(pfd[0]); /* execute CGI */ execlp(filename, filename, NULL); exit(0); } else { /* parent process */ close(pfd[1]); /* print output from CGI */ while((len=read(pfd[0], buffer, 1023))>0) { buffer[len] = '\0'; printf("%s\n", buffer); } /* waiting for CGI */ waitpid((pid_t)pid, &status, 0); } }
此範例相當易懂,不外乎是使用 fork() 建立一個新的 Process,再去執行一支外部 CGI,而主程式會等待外部 CGI 的輸出,再用 printf() 印出來 CGI 的輸出內容。而比較令人騷不著頭緒的部份,就是 pipe() 和 dup2() 的關係,使用 pipe() 可建立一組雙向的管線,範例中是一組有兩個整數值的陣列 pfd,這是一條水管,從 pfd[0] 進入的東西會從 pfd[1] 出來,反之亦然,除此之外,它也是可以跨 Process,達成兩個程式溝通的目的。除了建立 pipe,接著利用 dup2(),可以讓管線去取代外部程式的標準輸出(standard output),然後讓主程式用管線接收。
註:pipe() 回傳的是兩個檔案描述編號(file discriptions),需要用相應的檔案函數去操控它。
file discriptions <- 這個是指他的 pointer 嗎?
回覆刪除樓上,應該是 file descriptor XD
回覆刪除它常常縮寫成 fd,type是 int。