我试图理解与管道系统调用调用相关的结构。
int pipe(int pipefd[2]);
根据我的理解,将有一个与管道的读取端pipefd[0]
和写入端相关联的“读取”和“写入”内核缓冲区/结构。pipefd[1]
我真的很想要一些指向该管道的读/写端的结构的指针(没有双关语),我相信这只是文件描述符。例如,计算机如何知道在读取操作期间没有更多字节要“读取”传输,例如:
char tmpBuff[15];
bytesRead = read(filedes[0], tmpBuff, 15);
定义了什么结构来跟踪与filedes[0]
或filedes[1]
描述符相关的缓冲区、文件位置等?
根据手册页ssize_t read(int fd, void *buf, size_t count);
阅读(2) Linux 程序员手册
NAME read - 从文件描述符中读取
概要#include
ssize_t read(int fd, void *buf, size_t count);
返回值 成功时,返回读取的字节数(零表示文件结尾),并且文件位置提前了该数字。
必须有某种结构指向文件描述符引用的索引,以构成如下所示的某种结构。
struct file_info
{
char *start_buf;
char *end_buf;
int fileposition;
};
最后,出于好奇,是否可以从用户空间访问这些值,并制作一个程序,该程序会说“即将从文件描述符 foo 中读取,缓冲区中当前有 120 个字节,文件位置为 0”。由于缓冲区在用户级别无法访问(我认为),因此我们如何在仅知道文件描述符值的情况下访问此信息?
答案1
首先,您的一些问题可能会在这里得到解答: 管道缓冲区有多大?
管道是由内核维护的有界循环缓冲区。该pipe
系统调用创建一个新管道并将两个文件描述符与该管道关联,一个用于写入管道,另一个用于从管道读取。
通过关联的文件描述符写入管道,如果有空间,则将给定数据复制到该缓冲区。如果没有空间容纳数据,则对 write() 的调用会阻塞调用应用程序,直到空间可用为止。如果一个进程在管道上的 write() 操作中被阻止,并且其他一些进程/线程从管道中读取了足够的数据,这将允许被阻止的写入器完成其写入,则被阻止的写入器将被唤醒并允许继续进行。
这个过程对于读者来说也是类似的。如果读取进程尝试从管道读取数据,但没有任何内容可读取,则 read() 系统调用将阻塞,等待数据可用。如果某个进程在 pope 上的 read() 操作中被阻止,并且其他一些进程/线程将数据写入管道,这将允许被阻止的读取器完成其读取,则被阻止的读取器将被唤醒并允许继续进行。
关于管道的大小,您可以在以下手册页条目中找到一些信息man 7 pipe
:
管道容量
A pipe has a limited capacity. If the pipe is full, then a write(2) will block or fail, depending on whether the O_NONBLOCK flag is set (see below). Different implementations have different limits for the pipe capacity. Applications should not rely on a particular capacity: an application should be designed so that a reading process consumes data as soon as it is available, so that a writing process does not remain blocked. In Linux versions before 2.6.11, the capacity of a pipe was the same as the system page size (e.g., 4096 bytes on i386). Since Linux 2.6.11, the pipe capacity is 65536 bytes. Since Linux 2.6.35, the default pipe capacity is 65536 bytes, but the capacity can be queried and set using the fcntl(2) F_GETPIPE_SZ and F_SETPIPE_SZ operations. See fcntl(2) for more information.
以下是查询管道尺寸的示例程序:
#define _GNU_SOURCE
#include <assert.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int pipefds[2] = { -1, -1 };
assert(pipe(pipefds) == 0);
printf("pipe size: %d\n", fcntl(pipefds[0], F_GETPIPE_SZ));
// pipe will be closed on exit
return EXIT_SUCCESS;
}
运行该程序给我:
$ ./a.out
pipe size: 65536