2015-04-12 25 views
4

我有一個示例程序模式:不能切換到阻止使用的fcntl在linux

int main() 
{ 
    const char* fn = "/tmp/tmpfifo"; 
    int i = mkfifo(fn, 0666); 
    int fd = open(fn, O_RDONLY | O_NONBLOCK); 
    int flags = fcntl(fd, F_GETFL); 
    flags &= ~O_NONBLOCK; 
    fcntl(fd, F_SETFL, flags); 

    char buf[1024]; 
    int rd= read(fd, buf, 100); 
    cout << rd << endl; 
    remove(fn); 
    return 0; 
} 

似乎從文件描述符去除非阻塞標誌之後,read調用應該阻塞,直到一些被寫入先進先出,但我的程序總是運行沒有阻塞和rd=0結果。你能解釋這種行爲嗎?謝謝!

+0

看起來像C++而不是C.請參閱http://stackoverflow.com/questions/2784500/how-to-send-a-simple-string-between-two-programs-using-pipes –

+3

是C++, c區別重要嗎? – hovo

+0

當你從fifo讀入'rd = 0'的結果時,errno的值是否有變化? –

回答

2

您所看到的行爲是預期的。您已完成以下操作:

  1. 使用O_NONBLOCK打開FIFO的讀取結束,以便寫入器不需要存在於FIFO中。這保證open()將立即成功。
  2. 已禁用O_NONBLOCK後續讀取。現在你已經回到了一個相當於標準(阻塞)情況的位置,在這種情況下,FIFO有一個讀寫器,但是編寫者關閉了FIFO。在這一點上,讀者應該看到文件結束,這是你所看到的。
0

這很奇怪!我試了一個代碼,它打開沒有O_NONBLOCK的文件,然後分3個階段進行。第三階段沒有正確地處理O_NONBLOCK標誌結果重置!

#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <fcntl.h> 

int main() 
{ 
    char buf[1024]; 
    int rd; 
    const char* fn = "prova.txt"; 
    int i = mkfifo(fn, 0666); 
    int fd = open(fn, O_RDONLY); // | O_NONBLOCK); 
    int flags = fcntl(fd, F_GETFL); 
    //flags &= ~O_NONBLOCK; 
    printf("1) Waits!\t\tflags=0%08o\n",flags); 

    rd= read(fd, buf, 100); 
    printf("%d %o\n",rd,flags); 

    flags |= O_NONBLOCK; 
    printf("2) Doesn't wait!\tflags=0%08o\n",flags); 
    fcntl(fd, F_SETFL, flags); 
    rd= read(fd, buf, 100); 
    printf("%d %o\n",rd,flags); 

    //This doen't act the flag ???? 
    flags &= ~O_NONBLOCK; 
    fcntl(fd, F_SETFL, flags); 
    flags=fcntl(fd, F_GETFL); 
    printf("3) Waits!\t\tflags=0%08o\n",flags); 
    rd= read(fd, buf, 100); 
    printf("%d %o\n",rd,flags); 

    puts("End!"); 
    return 0; 
} 

這裏是命令序列和輸出:

[email protected]:~$ ./a.out & 
[2] 6555 
[email protected]:~$ echo xxx >> prova.txt 
1) Waits!  flags=000100000 
4 100000 
2) Doesn't wait! flags=000104000 
0 104000 
3) Waits!  flags=000100000 
0 100000 
End! 
[email protected]:~$ 
0

我看着你的代碼和乍一看好像它應該工作。沒有錯誤返回,你似乎沒有違反任何規則,但它只是沒有阻止。

所以我繼續追查read通話,看它是做什麼:

ftrace

而且它會一路the pipe_read function沒有任何企圖阻止。一旦它在那裏,它意識到管道另一端沒有人並返回EOF。

所以這顯然是通過設計,但與管道只有open調用將嘗試阻止,如果沒有作家,一旦open返回它只是假設必須有一個作家在另一端管道或你'非阻塞,並準備好處理。這有點合理。如果你想從管道上嘗試read,但作者已經離開了(或者從來沒有出現過),那麼你不想永遠在那裏等待。

如果您想等到編寫者打開管道,請不要在調用open時使用O_NONBLOCK。如果您確實在open中使用O_NONBLOCK,則管道另一端可能沒有任何人,並且read調用可能只是返回EOF而不會阻塞。

所以,總之,當你讀它時,確保管道另一端有人。