C Linux管道():从管道读取数据不会';I don’我并不总是解除对作家的封锁
我在Linux下使用管道时遇到问题。我想填充一根管子,以进一步阻止write的呼叫。另一个进程应该能够从管道中读取一些字符,从而允许另一个进程写入 示例代码:C Linux管道():从管道读取数据不会';I don’我并不总是解除对作家的封锁,c,linux,pipe,C,Linux,Pipe,我在Linux下使用管道时遇到问题。我想填充一根管子,以进一步阻止write的呼叫。另一个进程应该能够从管道中读取一些字符,从而允许另一个进程写入 示例代码: #include <stdio.h> #include <errno.h> #include <unistd.h> #include <stdlib.h> int main() { int pipefd[2]; int size = 65535; int total = 0; // Cr
#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;
}
相反,写入调用只有在读取4096字节后才被解除阻止。。。为什么
正常情况下,读取
成功完成X字节后,管道中应该有X字节的可用空间,因此写入
应该能够最多写入X字节,不是吗
我怎样才能让行为“读取1字节,写入1字节,等等”而不是“读取1字节,读取1,读取10,读取2000,…(直到读取4096字节),写入4096”?为什么它不能按您认为的方式工作
所以基本上我理解的是,管道与某种内核缓冲区的链表相关联。只有当其中一个缓冲区被清空时,等待写入管道的进程才会被唤醒。在您的例子中,这些缓冲区的大小恰好是4K
见:
具体来说,行:对缓冲区大小进行测试的地方,行:唤醒其他进程的决定完成的地方
管道缓冲区的大小实际上取决于内存页大小,请参阅
F_SETPIPE_SZ(int;自Linux 2.6.35起)
将fd引用的管道的容量至少更改为arg字节。
非特权流程可以将管道容量调整为介于
系统页面大小和/proc/sys/fs/pipe max size中定义的限制
(见程序(5))。尝试将管道容量设置为页面大小以下的尝试如下:
无声地向上取整到页面大小。非特权进程尝试
将管道容量设置为高于/proc/sys/fs/pipe max size yield中的限制
误差EPERM;特权进程(CAP_SYS_资源)可以覆盖
限制。为管道分配缓冲区时,内核可能会使用
容量大于arg,如果这便于实现。这个
F_GETPIPE_SZ操作返回实际使用的大小。正在尝试设置
管道容量小于当前用于存储的缓冲区空间量
存储数据生成错误EBUSY。
如何让它工作
您尝试实现的模式是经典的。但它的使用方式是这样的。人们从一根空管子开始。进程等待事件时,不读取空管道。要向事件发送信号的进程,请向管道中写入一个字节
我想我在Boost.Asio中看到了这一点,但我太懒了,找不到正确的引用。管道使用4kB的页面作为缓冲区,写入被阻止,直到有一个空页面用于写入,然后再阻止,直到再次满为止。这在本书中有很好的描述。如果您想使用该管道发送信号,您正在寻找相反的方案
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int pipefd[2];
// Create the pipe
if(pipe(pipefd) == -1)
{
perror("pipe()");
exit(EXIT_FAILURE);
}
// Fork
switch(fork())
{
case -1:
perror("fork()");
exit(EXIT_FAILURE);
case 0:
// Close unused write side
close(pipefd[1]);
while(1)
{
char c;
// Read only one byte
int ret = read(pipefd[0], &c, 1);
printf("Woke up\n", ret);
fflush(stdout);
}
default:
// Close unused read side
close(pipefd[0]);
size_t len = 0;;
char *str = NULL;
while(1)
{
int nbread;
char buf[65535];
while (getline(&str, &len, stdin)) {
if (sscanf(str, "%i", &nbread)) break;
};
// Write number byte asked
int ret = write(pipefd[1], buf, nbread);
printf("Written %d bytes\n", ret);
fflush(stdout);
}
}
return 0;
}
#包括
#包括
#包括
#包括
int main()
{
int-pipefd[2];
//创建管道
如果(管道(管道FD)=-1)
{
perror(“管道()”);
退出(退出失败);
}
//叉子
开关(fork())
{
案例1:
perror(“fork()”);
退出(退出失败);
案例0:
//关闭未使用的写端
关闭(pipefd[1]);
而(1)
{
字符c;
//只读一个字节
int-ret=read(pipefd[0],&c,1);
printf(“唤醒”,ret);
fflush(stdout);
}
违约:
//关闭未使用的读取端
关闭(pipefd[0]);
尺寸长度=0;;
char*str=NULL;
而(1)
{
int nbread;
char-buf[65535];
while(getline(&str,&len,stdin)){
如果(sscanf(str、%i、&nbread))断裂;
};
//请求写入数字字节
int-ret=写入(pipefd[1],buf,nbread);
printf(“已写入%d字节\n”,ret);
fflush(stdout);
}
}
返回0;
}
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int pipefd[2];
// Create the pipe
if(pipe(pipefd) == -1)
{
perror("pipe()");
exit(EXIT_FAILURE);
}
// Fork
switch(fork())
{
case -1:
perror("fork()");
exit(EXIT_FAILURE);
case 0:
// Close unused write side
close(pipefd[1]);
while(1)
{
char c;
// Read only one byte
int ret = read(pipefd[0], &c, 1);
printf("Woke up\n", ret);
fflush(stdout);
}
default:
// Close unused read side
close(pipefd[0]);
size_t len = 0;;
char *str = NULL;
while(1)
{
int nbread;
char buf[65535];
while (getline(&str, &len, stdin)) {
if (sscanf(str, "%i", &nbread)) break;
};
// Write number byte asked
int ret = write(pipefd[1], buf, nbread);
printf("Written %d bytes\n", ret);
fflush(stdout);
}
}
return 0;
}