gpt4 book ai didi

c - 无法同步 FIFO 上的阻塞读取和写入

转载 作者:行者123 更新时间:2023-11-30 18:05:46 24 4
gpt4 key购买 nike

我正在制作一个非常简单的程序,它由客户端使用的小型 API 和服务器进程组成。客户端进程和服务器进程通过一对 FIFO 进行通信(一个包含对服务器的请求,另一个包含来自服务器的响应)。

  • 服务器通过阻塞读取(O_RDWR 标志)继续读取请求 FIFO
  • 客户端在请求 FIFO 上写入请求(O_WRONLY 标志)
  • 服务器读取请求,对其进行处理并将响应写入响应 FIFO(O_WRONLY 标志)
  • 客户端读取响应(O_RDONLY 标志):如果服务器没有传送任何数据(我的意思是未定义的长缓冲区),则写入 FIFO 的响应就足够了,工作就完成了
  • 否则...
  • 客户端在响应中读取服务器将要发送数据的信息,因此它再次打开响应 FIFO(O_RDONLY 标志)
  • 服务器使用(O_WRONLY 标志)写入数据

最后一次写入似乎不会阻塞服务器进程,直到客户端在另一端读取:为什么?我缺少什么?为了实现我的目标,我必须在写入调用之前放置一个 sleep(1) ,但这仅适用于对服务器的某种请求:我如何帮助你帮助我?

服务器代码

                /* until here everything is ok: client read the response and waits for the buffer */
sleep(1);
/* open the FIFO and send the buffer */
if((fifofrom = open(FIFOFROMMMBOXD, O_WRONLY)) == -1) logMmboxd("error in opening FIFOFROM again for the buffer\n", 1);
else logMmboxd("opened FIFOFROM again for the buffer\n", 0);

if((write(fifofrom, mails, sizeof(mmbox_mail_complete)*m)) != sizeof(mmbox_mail_complete)*m) logMmboxd("error in writing FIFOFROM again for the buffer\n", 1);
else logMmboxd("written on FIFOFROM again for the buffer\n", 0);
close(fifofrom);

logMmboxd("messages list definitely sent\n", 0);

客户端代码

void lockUp(Request *request, Response *response, void **buffer)
{
int fifofrom, fifoto, lock;

/* lockto access the FIFOs */
if((lock = open(LOCK, O_RDONLY)) == -1) logMmboxman("error in opening LOCK\n", 1);
else logMmboxman("opened LOCK\n", 0);

if(flock(lock, LOCK_EX) == -1) logMmboxman("error in acquiring LOCK\n", 1);
else logMmboxman("acquired LOCK\n", 0);

/* open the FIFO and write the request */
if((fifoto = open(FIFOTOMMBOXD, O_WRONLY)) == -1) logMmboxman("error in opening FIFOTO\n", 1);
else logMmboxman("opened FIFOTO\n", 0);

if((write(fifoto, request, sizeof(Request))) != sizeof(Request)) logMmboxman("error in writing FIFOTO\n", 1);
else logMmboxman("written on FIFOTO\n", 0);
close(fifoto);

/* waiting for response on FIFOFROM */
if((fifofrom = open(FIFOFROMMMBOXD, O_RDONLY)) == -1) logMmboxman("error in opening FIFOFROM\n", 1);
else logMmboxman("opened FIFOFROM\n", 0);

if((read(fifofrom, response, sizeof(Response))) != sizeof(Response)) logMmboxman("error in reading FIFOFROM\n", 1);
else logMmboxman("read from FIFOFROM\n", 0);
close(fifofrom);

/* if size>0 then the server has to send a buffer of data to me! */
if(response->size)
{
if((fifofrom = open(FIFOFROMMMBOXD, O_RDONLY)) == -1) logMmboxman("error in opening FIFOFROM again for the buffer\n", 1);
else logMmboxman("opened FIFOFROM again for the buffer\n", 0);

*buffer = (void*)malloc(response->size);

if(read(fifofrom, *buffer, response->size) != response->size) logMmboxman("error in reading FIFOFROM again for the buffer\n", 1);
else logMmboxman("read from FIFOFROM again for the buffer\n", 0);
close(fifofrom);
}

/* read the response: I release the lock */
if(flock(lock, LOCK_UN) == -1) logMmboxman("error in releasing LOCK\n", 1);
else logMmboxman("released LOCK\n", 0);

return;
}

最佳答案

因此 (1) 您关于 FIFO 同步的推理是正确的; (2) Linux 搞砸的可能性几乎为零;所以(3)你有一个错误。

这很难说,但由于您最初将服务器 fifo 作为 O_RDWR 打开,也许您没有关闭您的想法?也许您正在运行第二个客户端,该客户端已作为读取器打开该 fifo,并且当您以 O_WRONLY 身份重新打开时,它不会阻塞?

无论如何,你真正的问题是你设计的协议(protocol)。我认为您不需要锁或保持打开和关闭 fifo。您确实需要一个合理的通信协议(protocol)。

通常是这样的:

(1) 服务器有一个众所周知的 fifo,客户端可以打开并写入。

(2) 客户端传递事务代码或指示这是初始请求的内容。其中包括服务器建立回客户端连接的一些方法。这可以是整个路径名,也可以只是客户端和服务器使用预先指定的路径来创建第二个 fifo 的 pid(例如,都打开“/tmp/myfifo_pid”或类似的名称)。

(3) 在客户端和服务器打开第二个 fifo 后,所有向服务器发出的进一步客户端请求都包含 pid(或其他内容),以便服务器知道在哪里输出请求。

(4) 完成所有操作后,客户端发送一个事务指示,以便服务器可以关闭第二个 fifo。客户端也做同样的事情。

(5) 对任意数量的客户端重复此操作。

请注意,您需要指定消息的格式。历史悠久的技术是使用长度代码(似乎是您正在尝试的)或某种消息结束分隔符(例如换行符)。

编辑

可能的消息格式:

长度|转码||数据|

其中 length 告诉您有多少后续字节组成整个消息、转码指定和操作(例如打开我的输出 fifo、关闭它、发送数据等),而 data 是适合事务的任何内容。

关于c - 无法同步 FIFO 上的阻塞读取和写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6082105/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com