2017-03-27 40 views
0

我想了解管道是如何工作的。根據我的理解,內核有一個文件描述符表,其中每個元素指向文件和管道等內容。因此,當指定正確的文件描述符時,進程可以寫入或讀取管道。關於posix管道關於內核fd表的困惑

在我在下面找到的例子中,文件描述符由一個數組組成,並且使用它創建一個管道。該程序然後叉,以便有一個子副本。這是我困惑的地方,孩子關閉fd [0],以至於無法從父母那裏收到信息?它將一些數據寫入fd [1]。父母然後關閉fd [1]並從fd [0]讀取。這對我來說似乎是錯誤的,父母是從錯誤的地方讀書?

int main(void) 
{ 
     int  fd[2], nbytes; 
     pid_t childpid; 
     char string[] = "Hello, world!\n"; 
     char readbuffer[80]; 

     pipe(fd); 

     if((childpid = fork()) == -1) 
     { 
       perror("fork"); 
       exit(1); 
     } 

     if(childpid == 0) 
     { 
       /* Child process closes up input side of pipe */ 
       close(fd[0]); 

       /* Send "string" through the output side of pipe */ 
       write(fd[1], string, (strlen(string)+1)); 
       exit(0); 
     } 
     else 
     { 
       /* Parent process closes up output side of pipe */ 
       close(fd[1]); 

       /* Read in a string from the pipe */ 
       nbytes = read(fd[0], readbuffer, sizeof(readbuffer)); 
       printf("Received string: %s", readbuffer); 
     } 

     return(0); 
} 

我錯了,實際上這兩個fd元素引用內核表中的同一個點嗎?直覺上我以爲它會創建兩個管道。如果它們在表格中的位置相同,那麼它可以解釋這些不同讀寫的管道結構是什麼?如果這太模糊了,我很抱歉,我真的有麻煩纏着它。任何幫助,將不勝感激。提前致謝!

+0

管道是一個內核管理的對象,其特點是(一部分)由*兩個*文件描述符 - 一個用於寫入,另一個用於讀取它。 'pipe()'函數創建這樣一個對象並將兩個FD記錄在指定的數組中;用於讀取的文件存儲在索引0和用於寫入索引1的文件中,您可以通過類比stdin和stdout文件描述符(分別爲0和1)記住它們。對於使用管道來關閉它不打算使用的端點的過程是常規的,有時是必需的。 –

回答

0

當你新建一個進程fork時,孩子有一個打開文件描述符的確切副本。這是如何實現的可以被認爲是「魔術」或其他什麼,因爲我們並不需要知道如何,只是它確實有效。他們分享他們,如果他們都試圖從stdin(例如)閱讀,你會得到不可預知的結果,因爲他們都從同一個地方閱讀。只有當所有進程關閉文件描述符時才真正關閉。

因此,在您的pipe的情況下,孩子和父母可以關閉他們不會使用的管道的末端,而不用擔心他們關心意外關閉的結束。如果其中一個打開另一個文件,它可能會重新使用最近關閉的文件描述符ID。