Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Linux管道():从管道读取数据不会';I don’我并不总是解除对作家的封锁_C_Linux_Pipe - Fatal编程技术网

C Linux管道():从管道读取数据不会';I don’我并不总是解除对作家的封锁

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

我在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;

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