UNIX / Linux IPC:从管道读取.如何在运行时知道数据长度?
我有一个子进程,它生成一些可变长度的输出,然后使用半双工管道将其发送给父进程.在父级中,如何使用read()函数?
由于数据每次都可以有不同的长度,我怎样才能在运行时知道数据的大小来为缓冲区做任何malloc()?可以在管道文件描述符上使用fstat()函数吗? 我知道read()函数将读取指定数量的字节,但如果在读取请求的字节之前到达文件末尾(不是EOF字符),则返回0. 我专门运行带有2.6.27-9内核的Ubuntu GNU / Linux. Richard Stevens在UNIX环境中的高级编程中的所有示例都在写入管道时指定了数据长度,或者依赖于fgets()stdio.h函数.由于我关心速度,我想尽可能远离使用stdio.h. 共享内存会更快吗? 谢谢, 解决方法
由于您似乎打算对管道中的所有数据进行单次读取,因此我认为以下内容将比分隔符编码或其他答案中建议的miniheader技术更好地为您服务:
从管道(7)手册页:
以下示例取自pipe(2)联机帮助页并进行了反转,以便子进行写入,父进行读取(只是为了确定).我还添加了一个可变大小的缓冲区.孩子会睡5秒钟.延迟将确保子项的exit()与pipeio无关(父项将在子项退出之前打印完整的行). #include <sys/wait.h> #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> char * slurpfd(int fd) { const int bytes_at_a_time = 2; char *read_buffer = NULL; int buffer_size = 0; int buffer_offset = 0; int chars_io; while (1) { if (buffer_offset + bytes_at_a_time > buffer_size) { buffer_size = bytes_at_a_time + buffer_size * 2; read_buffer = realloc(read_buffer,buffer_size); if (!read_buffer) { perror("memory"); exit(EXIT_FAILURE); } } chars_io = read(fd,read_buffer + buffer_offset,bytes_at_a_time); if (chars_io <= 0) break; buffer_offset += chars_io; } if (chars_io < 0) { perror("read"); exit(EXIT_FAILURE); } return read_buffer; /* caller gets to free it */ } int main(int argc,char *argv[]) { int pipefd[2]; pid_t cpid; assert(argc == 2); if (pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } cpid = fork(); if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (cpid == 0) { /* Child writes argv[1] to pipe */ close(pipefd[0]); /* Close unused read end */ write(pipefd[1],argv[1],strlen(argv[1]) + 1); close(pipefd[1]); /* Reader will see EOF */ /* sleep before exit to make sure that there will be a delay after the parent prints it's output */ sleep(5); exit(EXIT_SUCCESS); } else { /* Parent reads from pipe */ close(pipefd[1]); /* Close unused write end */ puts(slurpfd(pipefd[0])); close(pipefd[0]); wait(NULL); /* Wait for child */ _exit(EXIT_SUCCESS); } } 从您的评论中我现在看到,您可能希望在数据可用时读取数据,更新UI或其他任何内容,以反映系统的状态.为此,在非阻塞(O_NONBLOCK)模式下打开管道.重复读取任何可用的东西,直到-1返回并且errno == EAGAIN并进行解析.重复unil读取返回0,表示子项已关闭管道. 要为File *函数使用内存缓冲区,可以在GNU C库中使用fmemopen(). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |