命名管道未按预期工作。一遍又一遍地阅读相同的消息

Posted

技术标签:

【中文标题】命名管道未按预期工作。一遍又一遍地阅读相同的消息【英文标题】:named pipe is not working as expected. same message is being read again and again 【发布时间】:2016-07-12 05:58:19 【问题描述】:

我正在尝试使用命名管道在进程之间进行通信。它的行为不像预期的那样,它一次又一次地阅读相同的消息。

进程 1:(创建一个管道,并开始读取,直到它读取完或读取 100 条消息)

    char* myfifo = "/tmp/omgfifo"; 
    if ( feature_head == NULL ) 
        vty_out(vty,"%s%s", ERR_STR ,VTY_NEWLINE);
        return  CMD_WARNING ;
    
    vtysh_diag_list_features(feature_head,vty);
    /* Create UDS connection for ovs-appctl. */
    rc = mkfifo(myfifo,0777);
    if(rc == -1)
    
        vty_out(vty,"mkfifo errorno  : %d %s",errno,VTY_NEWLINE);
    
    fd = open(myfifo, O_RDONLY);
    if(fcntl(fd, F_GETFL ) & O_NONBLOCK)
    
        vty_out(vty,"non block is enabled %s",VTY_NEWLINE);  
    
    if(fd == -1)
    
        vty_out(vty,"fd errorno  : %d %s",errno,VTY_NEWLINE);
    
    else
    
    while(flag)
    
        retval ++;
        buf[0] = "\0"
        rc = read(fd,buf,MAX_BUF);
        if(retval > 100)
        
            flag = 0;
            break;
        
        if(rc == -1)
        
            flag = 0;
            vty_out(vty,"read errorno  : %d %s",errno,VTY_NEWLINE);
        
        else
        
        if(strlen(buf) > 3 && strcmp(buf,"over"))
        
            vty_out(vty,"gone case %s",VTY_NEWLINE);
            flag = 0;
        
        vty_out(vty,"%3d:%s %s",retval,buf,VTY_NEWLINE);
        
    
    close(fd);
    
    unlink(myfifo);
    vty_out(vty,"SIGN : done");
    return CMD_SUCCESS;

进程 2(写入同一管道)

int fd;
char * myfifo = "/tmp/omgfifo";

fd = open(myfifo, O_WRONLY);
if(fd == -1)

    vty_out(vty,"fd errorno  : %d %s",errno,VTY_NEWLINE);

else

    if(fcntl(fd, F_GETFL ) & O_NONBLOCK)

    vty_out(vty,"non block is enabled %s",VTY_NEWLINE);  

    if(write(fd, "Hi", sizeof("Hi"))== -1)
    
        vty_out(vty,"write h errorno  : %d %s",errno,VTY_NEWLINE);
        
if(write(fd, "Hi1", sizeof("Hi1"))== -1)
    
        vty_out(vty,"write h1 errorno  : %d %s",errno,VTY_NEWLINE);
        

if(write(fd, "over", sizeof("over")) == -1)
    
        vty_out(vty,"write o errorno  : %d %s",errno,VTY_NEWLINE);
        
if(write(fd, "Hi2", sizeof("Hi2")) == -1)
    
        vty_out(vty,"write h2 errorno  : %d %s",errno,VTY_NEWLINE);
        

if(write(fd, "Hi3", sizeof("Hi3")) == -1)
    
        vty_out(vty,"write h3 errorno  : %d %s",errno,VTY_NEWLINE);
        
if(close(fd)!=0)

    vty_out(vty,"close errorno  : %d %s",errno,VTY_NEWLINE);



    return 0;

进程1的输出(有时是Hi1,有时是结束

  1:Hi 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
SIGN : done

两个进程的fd都阻塞了。 有人可以解释一下为什么过程 1 一遍又一遍地阅读一些消息

【问题讨论】:

为什么要关闭并重新打开管道?尝试省略此 没有提到,我们不应该关闭并重新打开 是的,没有提到。但这绝对没有必要。它使代码更复杂、更慢。 【参考方案1】:

当您在写入部分关闭 fd 时,read 收到一个文件结尾并返回 0(并且缓冲区没有更改,因此它一直包含“Hi”)。您至少应该检查这种情况(通常您应该使用读取的返回值作为实际读取的字节数)。 一般来说,不能保证读取和写入之间存在完美匹配。 “写”只是将字符排入队列,“读”最多接收您作为第三个参数(MAX_BUF)传递的数字。所以发生的事情是,您在一次读取操作中接收到整组字符,然后在进一步读取时获得 EOF。拆分缓冲区并找到零件由您自己决定。

【讨论】:

很抱歉,这两个进程都是阻塞的。两个进程都没有启用非阻塞。 在关闭之前,进程 2 写入 Hi1 如果是这样,那么消息应该是 Hi5 对吗?关闭后,如何让进程 1 等待新读取而不是 EOF。因为如果你说的是真的意思,读就是继续读 EOF 我建议你打印也读取的返回值。这将帮助您弄清楚发生了什么。无论如何,您应该使用该值来确定接收缓冲区中有多少字符是有效的。 我已经修改了代码,正如你提到的 read 正在阅读 eof 。但为什么呢? 嗯...它的行为就好像在第一次写入后仍然有关闭一样。奇怪的。顺便说一句,我建议你用“memset(buf,0,MAX_BUF )" 以确保不重复使用旧值。

以上是关于命名管道未按预期工作。一遍又一遍地阅读相同的消息的主要内容,如果未能解决你的问题,请参考以下文章

据说随机 API 一遍又一遍地返回相同的东西

一遍又一遍地运行相同的junit测试的简单方法?

试图将200个jpg文件转换为带有ImageMagick的mp4。一遍又一遍地接收相同的错误

Google Cloud Run 一遍又一遍地错误运行

GGplot多个页面一遍又一遍地打印相同的第一个图

为啥 OnPreRender 被一遍又一遍地调用?