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

发布于 2024-12-04 07:57:00 字数 2014 浏览 0 评论 0原文

我正在创建一个相当大的项目作为家庭作业,我需要创建一个服务器程序来监听 2 个 fifo,客户端将在其中写入。

一切正常,但有一些事情让我生气:每当我执行一个操作(由客户端和服务器之间的一些写入/读取组成)时,当我关闭客户端上的 fifos 时,看起来服务器“认为”仍然有有人让这些 fifo 保持打开状态。

因此,服务器在每次操作后都会尝试读取 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

I'm creating a quite-big project as an homework where I need to create a server program which listen to 2 fifos, where clients will write.

Everything works, but there is something that is making me angry: whenever I do an operation, which is composed from some write/reads between client and server, when I close fifos on client, it looks like server "think" that there is still someone keeping those fifos opened.

Due to this, the server tries to read 64 byte after each operation, obviusly failing (reading 0 bytes). Only one time per operation this thing happens, it doesn't keep trying to read 64 byte

It doesn't create any problem to clients but it's really strange and I hate those type of bugs

I think it's a problem connected to open/close and to the fact that clients use a lock.

Note, flags used on the open operation are specified in this pseudocode text

Server behaviour:

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

Client behaviour:

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)

I can't post directly the code, except from the functions used for networking because the project is quite big and I don't use syscalls directly. Here you are:

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;
}

Any help will be appreciated, thanks.

EDIT 1:

Client output: http://pastie.org/2523854
Server output (strace): http://pastie.org/2523858

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

水波映月 2024-12-11 07:57:00

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

Zero bytes returned from (blocking) read() indicates an end of file, i.e., that the other end has closed the FIFO. Read the manpage for read.

只涨不跌 2024-12-11 07:57:00

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

这就是它应该工作的方式。

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

The zero bytes result from read() means that the other process has finished. Now your server must close the original file descriptor and reopen the FIFO to serve the next client. The blocking operations will resume once you start working with the new file descriptor.

That's the way it is supposed to work.

AFAIK, after you get the zero bytes, further attempts to read on the file descriptor will also return 0 bytes, in perpetuity (or until you close the file descriptor). Even if another process opens the FIFO, the original file descriptor will continue to indicate EOF (the other client process will be hung waiting for a server process to open the FIFO for reading).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文