我對昨天提出的現有問題感到困惑:
Recursive piping in Unix again。管道()帶叉()遞歸:文件描述符處理
我重新張貼問題的代碼:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
void pipeline(char * ar[], int pos, int in_fd);
void error_exit(const char*);
static int child = 0; /* whether it is a child process relative to main() */
int main(int argc, char * argv[]) {
if(argc < 2){
printf("Usage: %s option (option) ...\n", argv[0]);
exit(1);
}
pipeline(argv, 1, STDIN_FILENO);
return 0;
}
void error_exit(const char *kom){
perror(kom);
(child ? _exit : exit)(EXIT_FAILURE);
}
void pipeline(char *ar[], int pos, int in_fd){
if(ar[pos+1] == NULL){ /*last command */
if(in_fd != STDIN_FILENO){
if(dup2(in_fd, STDIN_FILENO) != -1)
close(in_fd); /*successfully redirected*/
else error_exit("dup2");
}
execlp(ar[pos], ar[pos], NULL);
error_exit("execlp last");
}
else{
int fd[2];
pid_t childpid;
if ((pipe(fd) == -1) || ((childpid = fork()) == -1)) {
error_exit("Failed to setup pipeline");
}
if (childpid == 0){ /* child executes current command */
child = 1;
close(fd[0]);
if (dup2(in_fd, STDIN_FILENO) == -1) /*read from in_fd */
perror("Failed to redirect stdin");
if (dup2(fd[1], STDOUT_FILENO) == -1) /*write to fd[1]*/
perror("Failed to redirect stdout");
else if ((close(fd[1]) == -1) || (close(in_fd) == - 1))
perror("Failed to close extra pipe descriptors");
else {
execlp(ar[pos], ar[pos], NULL);
error_exit("Failed to execlp");
}
}
close(fd[1]); /* parent executes the rest of commands */
close(in_fd);
pipeline(ar, pos+1, fd[0]);
}
}
這是存在的錯誤是:
Example:
./prog ls uniq sort head
gives:
sort: stat failed: -: Bad file descriptor
這建議是:「不要關閉文件描述符fd中的解決方案[1]和in_fd在子進程中,因爲它們已經在父進程中關閉了。「
我的困惑:(對不起,我在Linux的新手)
按我的書「開始的Linux程序設計」,當我們fork()的一個過程,那麼文件描述符也被複制。因此父母和孩子應該有不同的文件描述符。這與答案矛盾。
我嘗試:
我試圖運行此代碼我自己和我看到的問題就來了只有當我關閉這兩個進程(父母和子女)的「in_fd」文件描述符。它不依賴於fd [1]。
另外,有趣的是,如果我嘗試./prog ls sort head
它可以正常工作,但是當我嘗試./prog ls sort head uniq
時,它給出了head
上的讀取錯誤。
我的想法: 的in_fd
文件描述符只是這個功能的輸入int變量。看起來,即使在fork之後,只有一個文件描述符仍然是由父節點和子節點共享的。但我無法理解如何。
請看我的回答,如果我無法澄清任何事情,請在那裏發表評論。 – Dipto
'當in_fd == STDIN_FILENO時'dup2(in_fd,STDIN_FILENO)'有問題。您在代碼中的某個點上捕獲此問題,但在另一個點上忽略它。 –
@WilliamPursell你能解釋一下,如果in_fd最初是STDIN_FILENO會導致什麼問題?謝謝! – user3154219