[英]Can't write twice into a pipe in C
我編寫了一個簡短的C程序,以學習IPC基礎。 該程序由一個試圖向管道寫入兩次的子進程和一個試圖讀取兩條消息的父進程組成。 消息在text1
和text2
。 執行后,父進程僅讀取第一條消息。
子進程的輸出如下:
I write text1 in pipe
I write text2 in pipe
父母通過管道從孩子那里收到的短信是: Hi Dady, I'm your child and text1!
。
這是代碼:
main(void){
int fd0[2], nbytes;
pid_t childpid;
ssize_t errorfi;
char text1[] = "Hi Dady, I'm your child and text1!\n";
char text2[] = "Hi Dady, I'm your child and text2!\n";
char readbuffer[80],msg[80];
pipe(fd0);
if((childpid = fork()) == -1)
{
perror("fork");
_exit(1);
}
if(childpid == 0)
{ //child process
close(fd0[0]);
fprintf (stderr, "I write text1 in pipe\n");
errorfi = (write(fd0[1], text1, (strlen(text1)+1)));
if (errorfi <0 )
{
fprintf (stderr, "errorfi = %d\n", errorfi);
fprintf (stderr, "error writting texto1 in fd0 pipe %s\n",strerror(errorfi));
_exit (EXIT_FAILURE);
}
fprintf (stderr, "I write text2 in pipe\n");
errorfi = (write(fd0[1], text2, (strlen(text2)+1)));
if (errorfi <0 )
{
fprintf (stderr, "errorfi = %d\n", errorfi);
fprintf (stderr, "error writting texto2 in fd0 pipe %s\n",strerror (errorfi));
_exit (EXIT_FAILURE);
}
_exit(0);
else
{ //parent process
close(fd0[1]);
nbytes = read(fd0[0], readbuffer, sizeof(readbuffer));
printf("text received in parent from child trough pipe:%s\n", readbuffer);
}
return(0);}
為什么我只閱讀text1
?
這個問題比AB_的答案更糟糕。 (現已刪除:此答案建議再次閱讀)
您可能在父母與子女之間存在比賽條件。 如果孩子在父母閱讀第一條消息之前只能寫一次,那么一切都會好的(前提是您閱讀了兩次)。 但是,如果孩子在父母讀第一(或唯一)讀之前寫兩次,則將獲得72個字符...但是您只會打印第一條消息!
為了證明這一點,我對父部分進行了一些修改,等待0.5秒並顯示nbytes:
{ //parent process
close(fd0[1]);
usleep(500);
nbytes = read(fd0[0], readbuffer, sizeof(readbuffer));
printf("text received in parent from child trough pipe (%d) :%s\n",
nbytes,讀取緩沖區); }
我得到:
I write text1 in pipe
I write text2 in pipe
text received in parent from child trough pipe (72) :Hi Dady, I'm your child and text1!
為什么會得到72個字符並且只打印前半部分? 因為readbuffer[36] == '\\0'
! 並且所有C字符串函數都使用NULL作為字符串終止符。
因此,規則是當您通過管道或套接字傳遞文本時,除非對它們進行特殊處理 (*), 否則永遠不要發送終止null。
您應該在孩子中使用:
errorfi = write(fd0[1], text2, strlen(text1));
僅發送非null字符並避免出現競爭狀況的風險。
(*)根據Mat的評論進行編輯:在串行通道(管道,套接字或...串行線)中,必須使用size + data或定界符來清楚地標識數據塊。 我通常避免使用NULL作為分隔符(在C或C ++程序中),因為它會阻止所有字符串函數的使用。 但是您要照顧好它並繼續處理第一個null以外的內容,NULL是一個很好的分隔符,因為它不在文本中使用(這就是為什么它是C分隔符的原因)。
並且不要忘記:單個讀取的大小(至少在串行線路和管道上)可以大於或小於單個寫入的大小:例如,睡眠將兩個寫入連接在一起。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.