2010-08-12 142 views
9

我已經C代碼下列位,它從管道讀取信息,然後應該阻止,但它從未塊讀不阻塞命名管道

int pipe_fd; 
int res; 
int open_mode = O_RDONLY; 
char buf[100]; 
int bytes_read = 0; 

memset (buf, '\0', sizeof(buf)); 
pipe_fd = open(FIFO_NAME, open_mode); 

if (access(FIFO_NAME, F_OK) == -1) 
{ 
    res = mkfifo(FIFO_NAME, 0777); 
    if (res != 0) 
    { 
      fprintf (stderr, "Could not create fifo %s\n", FIFO_NAME); 
      exit (EXIT_FAILURE); 
    } 
} 

for(;;) 
{   
    do  
    {  
     res = read(pipe_fd, buf, sizeof(buf)); 
     bytes_read += res; 
    }while (res > 0); 

    // process data then go back and block 
    ............ 
} 

這是由某些代碼在一個bash腳本發送簡單的緩衝像這樣的」 ./test 1'

#!/bin/bash 

pipe=/tmp/pipe 

if [[ ! -p $pipe ]]; then 
    echo "Reader not running" 
    exit 1 
fi 

if [[ "$1" ]]; then 
    echo "some string" >$pipe 
else 
    echo "q" >$pipe 
fi 

我運行在GDB的C代碼程序,最初它在讀取的塊,但只要我叫bash腳本的C代碼不再塊,它確實成功從 讀取緩衝區中的數據,然後每次讀取時都有0個字節讀取所以不知道爲什麼它不再阻塞。 '一些字符串'的數據在另一端正確接收。

我只需要坐在那裏等待數據處理,然後回去等待更多

回答

14

我運行在GDB的C代碼程序,最初它在讀取的塊,但只要我調用bash腳本的C代碼不再阻塞,它成功地從緩衝區中讀取數據,然後每次讀取時都有0個字節讀取,所以不知道爲什麼它不再阻塞。 '一些字符串'的數據在另一端正確接收。

0表示EOF。只有在連接有讀寫的進程時才能讀取或寫入FIFO。當沒有更多的作者(您的shell腳本終止)時,讀者將通過返回EOF的read()得到通知。

FIFO的行爲是那樣要與殼管邏輯例如爲:

$ mkfifo ./tmp1 
$ cat <input> ./tmp1 & 
$ cat <./tmp1> /dev/null 

兼容。如果read()不會EOF返回,第二cat將永遠阻塞。

我只需要坐在那裏等待數據處理,然後回去等待更多

在你的C程序必須重新open()的FIFO後read()返回EOF第一次。

P.S.爲您找到quite nice FIFO summary。檢查第二頁上的表格。所以C是得到一個「EOF」條件

+0

非常感謝,沒有意識到。在重新開放之前,我應該在收到EOF之後關閉fifo – tech74 2010-08-12 11:35:59

+0

@ tech74:顯然。 'open()'分配新的文件描述符 - 舊的必須使用'close()'釋放。作家將阻止,直到您重新打開FIFO再次讀取。 – Dummy00001 2010-08-12 12:03:45

+1

+1鏈接! – 2012-11-05 11:31:36

0

您的bash腳本關閉管道。

因此,寫腳本需要打開管道並重復使用打開的描述符來寫入內容並最終關閉打開的描述符。

0

我覺得寫邊shell腳本關閉管道每當回聲東西