在fifo上打开系统调用没有阻塞?

时间:2011-09-12 17:15:45

标签: c unix fifo

我正在创建一个非常大的项目作为家庭作业,我需要创建一个服务器程序,听取2个FIFO,客户将在那里写。

一切正常,但有些东西让我生气:每当我做一个由客户端和服务器之间的一些写/读操作组成的操作时,当我在客户端关闭fifos时,看起来服务器“认为”那个仍然有人保持这些十五人开放。

由于这个原因,服务器在每次操作后尝试读取64字节,显然失败(读取0字节)。 每次操作只发生一次这件事,它不会继续尝试读取64字节

它不会给客户带来任何问题,但它真的很奇怪,我讨厌那些类型的错误

我认为这是一个与开/关相关的问题以及客户使用锁的事实。

注意,打开操作中使用的标志在此伪代码文本中指定

服务器行为:

Open Fifo(1) for READING (O_RDONLY)
Open Fifo(2) for WRITING (O_WRONLY)
Do some operations
Close Fifo(1)
Close Fifo(2)

客户行为:

Set a lock on Fifo(1) (waiting if there is already one)
Set a lock on Fifo(2) (same as before)
Open Fifo(1) for WRITING (O_WRONLY)
Open Fifo(2) for READING (O_RDONLY)
Do some operations
Close Fifo(1)
Close Fifo(2)
Get lock from Fifo(1)
Get lock from Fifo(2)

我不能直接发布代码,除了用于网络的函数,因为项目非常大,我不直接使用系统调用。你在这里:

int Network_Open(const char* path,int oflag)
{
    return open(path,oflag);
}

ssize_t Network_IO(int fifo,NetworkOpCodes opcode,void* data,size_t dataSize)
{
    ssize_t retsize = 0;
    errno = 0;

    if (dataSize == 0) return 0;

    while ((retsize = (opcode == NetworkOpCode_Write? write(fifo,data,dataSize) : read(fifo,data,dataSize))) < 0)
    {
        if (errno != EINTR) break;
    }

    return retsize;
}

Boolean Network_Send(int fifo,const void* data,size_t dataSize)
{
    return ((ssize_t)dataSize) == Network_IO(fifo,NetworkOpCode_Write,(void*)data,dataSize);
}

Boolean Network_Receive(int fifo,void* data,size_t dataSize)
{
    return ((ssize_t)dataSize) == Network_IO(fifo,NetworkOpCode_Read,data,dataSize);
}

Boolean Network_Close(int fifo)
{
    if (fifo >= 0)
        return close(fifo) == 0;
}

任何帮助将不胜感激,谢谢。

编辑1:

客户端输出: http://pastie.org/2523854 服务器输出(strace): http://pastie.org/2523858

2 个答案:

答案 0 :(得分:3)

从(阻塞)read()返回的零字节表示文件结束,即另一端已关闭FIFO。阅读联机帮助页以供阅读。

答案 1 :(得分:2)

来自read()的零字节结果表示其他进程已完成。现在,您的服务器必须关闭原始文件描述符并重新打开FIFO以服务下一个客户端。一旦开始使用新文件描述符,阻塞操作将恢复。

这就是它的工作方式。

AFAIK,在获得零字节后,进一步尝试读取文件描述符也将永久返回0字节(或直到您关闭文件描述符)。即使另一个进程打开FIFO,原始文件描述符仍将继续指示EOF(其他客户端进程将挂起,等待服务器进程打开FIFO进行读取)。