gpt4 book ai didi

c - Linux 管道 () : Reading from a pipe doesn't always unblock writers

转载 作者:太空狗 更新时间:2023-10-29 12:02:41 26 4
gpt4 key购买 nike

我在 Linux 下使用管道时遇到问题。我想填充管道以进一步阻止写入的调用。另一个进程应该能够从应该允许另一个进程写入的管道中读取一些字符。

示例代码:

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

int main()
{
int pipefd[2];
int size = 65535;
int total = 0;

// Create the pipe
if(pipe(pipefd) == -1)
{
perror("pipe()");
exit(EXIT_FAILURE);
}

// Fill in (almost full = 65535 (full - 1 byte))
while(total < size)
{
write(pipefd[1], &total, 1);
total++;
}

// Fork
switch(fork())
{

case -1:
perror("fork()");
exit(EXIT_FAILURE);
case 0:
// Close unused read side
close(pipefd[0]);
while(1)
{
// Write only one byte, value not important (here -> total)
int ret = write(pipefd[1], &total, 1);
printf("Write %d bytes\n", ret);
}
default:
// Close unused write side
close(pipefd[1]);
while(1)
{
int nbread;
scanf("%4i", &nbread);
char buf[65535];
// Read number byte asked
int ret = read(pipefd[0], buf, nbread);
printf("Read %d bytes\n", nbread);
}
}

return 0;
}

我不明白下面的行为。进程写了最后一次因为我没有把管道完全填满,正常。但之后,写入被阻塞(管道已满),任何读取都应该解除阻塞等待的写入调用。

test@pc:~$./pipe
Write 1 bytes
4095
Read 4095 bytes
1
Read 1 bytes
Write 1 bytes
Write 1 bytes
Write 1 bytes
Write 1 bytes
Write 1 bytes
Write 1 bytes
...

相反,写调用只有在读取 4096 字节后才会解除阻塞...为什么????

通常,在 read 成功 X 字节后,管道中应该有 X 字节的可用空间,因此 write 应该能够写入 X字节,不是吗?

如何让行为“读取 1 个字节,写入 1 个字节,等等”而不是“读取 1 个字节,读取 1 个,读取 10,读取 2000,...(直到读取 4096 字节),写入 4096”?

最佳答案

为什么它不像你想的那样工作

所以基本上我的理解是你的管道与某种内核缓冲区链表相关联。只有当其中一个缓冲区被清空时,等待写入管道的进程才会被唤醒。在您的情况下,这些缓冲区的大小恰好是 4K。

参见:http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/pipe.c?id=HEAD

具体行:281在缓冲区大小测试完成的地方,行:287唤醒其他进程的决定已完成。

管道缓冲区的大小确实取决于内存页面大小,参见man fcntl

F_SETPIPE_SZ(整数;自 Linux 2.6.35 起)

Change the capacity of the pipe referred to by fd to be at least arg bytes. An unprivileged process can adjust the pipe capacity to any value between the system page size and the limit defined in /proc/sys/fs/pipe-max-size (see proc(5)). Attempts to set the pipe capacity below the page size are silently rounded up to the page size. Attempts by an unprivileged process to set the pipe capacity above the limit in /proc/sys/fs/pipe-max-size yield the error EPERM; a privileged process (CAP_SYS_RESOURCE) can override the limit. When allocating the buffer for the pipe, the kernel may use a capacity larger than arg, if that is convenient for the implementation. The F_GETPIPE_SZ operation returns the actual size used. Attempting to set the pipe capacity smaller than the amount of buffer space currently used to store data produces the error EBUSY.

如何让它发挥作用

您尝试实现的模式是经典。但它被用来绕过。人们从空管开始。等待事件的进程,读取 空管道。进程想要发出事件信号,将单个字节写入管道。

我想我在 Boost.Asio 中看到过,但我懒得找到正确的引用。

关于c - Linux 管道 () : Reading from a pipe doesn't always unblock writers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29233352/

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