2013-01-25 39 views
2

我試圖在使用fifo的兩個進程之間來回發送信息。它工作到一個點,但然後一個閱讀塊。我懷疑Process2是錯誤的地方。讀取中間值時雙向fifo通信塊

處理1:

#include<fcntl.h> 
#include<sys/types.h> 
#include<sys/stat.h> 
main() 
{ 
char oprtr; 
int fd1,fd0; 
float oprnd1,oprnd2,result; 

mkfifo("fifo1",0777); 
fd1=open("fifo1",O_RDWR); 

printf("fd1:%d\n",fd1); 
printf("Add(+)\n"); 
printf("subtract(-)\n"); 
printf("multiply(*)\n"); 
printf("division(/)\n"); 

printf("Enter operator\n"); 
scanf("%c",&oprtr); 
getchar(); 
write(fd1,&oprtr,sizeof(oprtr)); 

printf("Enter oprnd1\n"); 
scanf("%f",&oprnd1); 
getchar(); 
write(fd1,&oprnd1,sizeof(oprnd1)); 

fd0=dup(fd1); 
printf("Enter oprnd2\n"); 
scanf("%f",&oprnd2); 
getchar(); 

if(write(fd0,&oprnd2,sizeof(oprnd2))==0) 
    perror("write : oprnd2:"); 
else 
    printf("writing oprnd2 done\n"); 

read(fd1,&result,sizeof(result)); 
printf("Result:%f\n",result); 
} 

過程2:

#include<fcntl.h> 
#include<sys/types.h> 
#include<sys/stat.h> 
main() 
{ 
int fd2,fd3; 
char oprtr; 
float oprnd1,oprnd2,result; 
fd2=open("fifo1",O_RDWR); 
printf("fd2:%d\n",fd2); 

read(fd2,&oprtr,sizeof(oprtr)); 
printf("oprtr:%c\n",oprtr); 

read(fd2,&oprnd1,sizeof(oprnd1)); 
printf("oprnd1:%f\n",oprnd1); 

fd3=dup(fd2); 

這就是讀取功能被阻塞

上述兩個讀()調用出現工作正常,但以下read()調用被阻止。爲什麼?

if(read(fd3,&oprnd2,sizeof(oprnd2))==0) ////This is the problem 
    perror("read : oprnd2:"); 
else 
    printf("oprnd2:%f\n",oprnd2); 

switch(oprtr) 
{ 
case '+':result=oprnd1+oprnd2; 
      write(fd2,&result,sizeof(result));break; 
case '-':result=oprnd1-oprnd2; 
      write(fd2,&result,sizeof(result));break; 
case '*':result=oprnd1*oprnd2; 
      write(fd2,&result,sizeof(result));break; 
case '/':result=oprnd1/oprnd2; 
      write(fd2,&result,sizeof(result));break; 
default: printf("Wrong Choice\n");break; 
} 
} 

端子1:

Add(+) 
subtract(-) 
multiply(*) 
division(/) 
Enter operator 
+ 
Enter oprnd1 
14.56 
Enter oprnd2 
16.44 
writing oprnd2 done 
Result:16.440089 

2號航站樓:

fd2:3 
oprtr:+ 
oprnd1:14.560000 

然後,它只是被封鎖

+0

看起來您正試圖在兩個進程之間創建客戶端 - 服務器關係。如果你是,而且這是一個嚴肅的項目(即不只是一個演示或玩具),我建議你考慮使用遠程過程調用(RPC)。 – Scott

回答

2

短期和簡單的答案是,你不應該使用一個單一的FIFO用於雙向通信而無需外部同步n機制。

詳細說明:Unix管道或fifo並不是最佳的可視化管道類型管道。 它更像是一個儲罐,管道通向它。標準用法是一個過程寫入,從而填充罐體,另一個過程讀取,從而排空罐體。在你的計劃中,所有寫到前沿的東西都會放在坦克裏,直到有人前來閱讀,先到先得。所以你的Process1程序讀取16.44的值,它從oprnd2寫回到result。這使得容器變空,所以Process2沒有任何內容可以讀取。這歸結於競爭條件。我懷疑,如果你幾次運行這兩個命令,他們會按照你想要的方式工作幾次。

如果您只是想要驗證概念,請在fifo前read之前向Process1添加sleep。更好的解決方案是使用兩個fifos,每個方向一個。或者你可以爲Process2設計一些方法讓Process1知道它(Process2)已經讀取了操作符和兩個操作數,並且寫出了結果 - 例如信號或信號量 - 但這可能比它的值得更麻煩。

另一方面,我強烈建議不要使用scanf以外的任何東西,除了玩具,演示或丟棄原型類型的程序。如果用戶點擊輸入,程序將永遠坐在那裏。我建議讀一行(確保解決緩衝區溢出),然後在其上調用sscanf

哦,還有,請縮進你的代碼。

+0

非常感謝你,解決了問題 – Neeraj

+0

不使用'scanf'的另一個原因 - 你顯然知道它將新行保留在輸入緩衝區中。我希望你們明白,總的來說,它的內容與其所需要的一樣多,並且其餘部分未讀。所以,如果你的用戶感到困惑並且在輸入「'+ - *'」時會迴應「'Enter operator'」提示符,那麼'scanf'將讀取'+','getchar()'將讀取' ',並且'*'將留在輸入流中,它會破壞'scanf(「%f」,&oprnd1);'。 – Scott

+0

是的,這是真的,我將不得不照顧這一點。再次感謝此支持@Scott – Neeraj