为什么我的写入没有阻塞到这个管道?
Why are my writes not blocking to this pipe?
我正在写一个小Linux fifo 测试程序。
我使用 mkfifo mpipe
创建了一个管道。该程序应该为每个发送给它的参数执行一次写入。如果没有发送任何参数,那么它会从管道执行一次读取。
这是我的代码
int main(int argc, char *argv[])
{
if (argc > 1)
{
int fd = open("./mpipe", O_WRONLY);
int i = 1;
for (i; i < argc; i++)
{
int bytes = write(fd, argv[i], strlen(argv[i]) + 1);
if (bytes <= 0)
{
printf("ERROR: write\n");
close(fd);
return 1;
}
printf("Wrote %d bytes: %s\n", bytes, argv[i]);
}
close(fd);
return 0;
}
/* Else perform one read */
char buf[64];
int bytes = 0;
int fd = open("./mpipe", O_RDONLY);
bytes = read(fd, buf, 64);
if (bytes <= 0)
{
printf("ERROR: read\n");
close(fd);
return 1;
}
else
{
printf("Read %d bytes: %s\n", bytes, buf);
}
close(fd);
return 0;
}
我希望行为是这样的...
我调用 ./pt hello i am the deepest guy
,我预计它会阻塞 6 次读取。相反,一次读取似乎足以触发多次写入。我的输出看起来像
# Term 1 - writer
$: ./pt hello i am the deepest guy # this call blocks until a read, but then cascades.
Just wrote hello
Just wrote i
Just wrote am
Just wrote the # output ends here
# Term 2 - reader
$: ./pt
Read 6 bytes: hello
有人可以帮忙解释一下这种奇怪的行为吗?我认为每次读取都必须与管道通信方面的写入相匹配。
那里发生的事情是,内核在 open(2)
系统调用中阻止写入进程,直到您 reader 打开它进行读取。 (fifo 要求两端都连接到进程才能工作)一旦 reader 执行第一个 read(2)
调用(写入器或 reader 块,谁先进行系统调用)内核将所有数据从 writer 传递到 reader,并唤醒两个进程(这就是只接收第一个命令行参数的原因,而不是来自 writer 的前 16 个字节,你只得到六个字符 {'h', 'e', 'l', 'l', 'o', '[ =13=]' }
来自阻止作者)
最后,由于 reader 刚刚关闭了 fifo,作者被 SIGPIPE
信号杀死,因为没有更多的 reader 打开 fifo。如果你在 writer 进程上安装一个信号处理程序(或忽略信号)你会从 write(2)
系统调用中得到一个错误,告诉你没有更多的 readers 在 fifo 上被阻塞(EPIPE
errno 值)在阻塞写入时。
请注意,这是一个功能,而不是一个错误,一种知道在关闭并重新打开 fifo 之前写入不会达到任何 reader 的方法。
内核为整个 read(2)
或 write(2)
调用阻塞了 fifo 的索引节点,因此即使另一个进程在 fifo 上执行另一个 write(2)
也会被阻塞,而你'我不会从第二个作者那里得到关于 reader 的数据(如果你有的话)。喜欢的话可以试试,启动两个writer,看看会发生什么。
$ pru I am the best &
[1] 271
$ pru
Read 2 bytes: I
Wrote 2 bytes: I
Wrote 3 bytes: am
[1]+ Broken pipe pru I am the best <<< this is the kill to the writer process, announced by the shell.
$ _
我正在写一个小Linux fifo 测试程序。
我使用 mkfifo mpipe
创建了一个管道。该程序应该为每个发送给它的参数执行一次写入。如果没有发送任何参数,那么它会从管道执行一次读取。
这是我的代码
int main(int argc, char *argv[])
{
if (argc > 1)
{
int fd = open("./mpipe", O_WRONLY);
int i = 1;
for (i; i < argc; i++)
{
int bytes = write(fd, argv[i], strlen(argv[i]) + 1);
if (bytes <= 0)
{
printf("ERROR: write\n");
close(fd);
return 1;
}
printf("Wrote %d bytes: %s\n", bytes, argv[i]);
}
close(fd);
return 0;
}
/* Else perform one read */
char buf[64];
int bytes = 0;
int fd = open("./mpipe", O_RDONLY);
bytes = read(fd, buf, 64);
if (bytes <= 0)
{
printf("ERROR: read\n");
close(fd);
return 1;
}
else
{
printf("Read %d bytes: %s\n", bytes, buf);
}
close(fd);
return 0;
}
我希望行为是这样的...
我调用 ./pt hello i am the deepest guy
,我预计它会阻塞 6 次读取。相反,一次读取似乎足以触发多次写入。我的输出看起来像
# Term 1 - writer
$: ./pt hello i am the deepest guy # this call blocks until a read, but then cascades.
Just wrote hello
Just wrote i
Just wrote am
Just wrote the # output ends here
# Term 2 - reader
$: ./pt
Read 6 bytes: hello
有人可以帮忙解释一下这种奇怪的行为吗?我认为每次读取都必须与管道通信方面的写入相匹配。
那里发生的事情是,内核在 open(2)
系统调用中阻止写入进程,直到您 reader 打开它进行读取。 (fifo 要求两端都连接到进程才能工作)一旦 reader 执行第一个 read(2)
调用(写入器或 reader 块,谁先进行系统调用)内核将所有数据从 writer 传递到 reader,并唤醒两个进程(这就是只接收第一个命令行参数的原因,而不是来自 writer 的前 16 个字节,你只得到六个字符 {'h', 'e', 'l', 'l', 'o', '[ =13=]' }
来自阻止作者)
最后,由于 reader 刚刚关闭了 fifo,作者被 SIGPIPE
信号杀死,因为没有更多的 reader 打开 fifo。如果你在 writer 进程上安装一个信号处理程序(或忽略信号)你会从 write(2)
系统调用中得到一个错误,告诉你没有更多的 readers 在 fifo 上被阻塞(EPIPE
errno 值)在阻塞写入时。
请注意,这是一个功能,而不是一个错误,一种知道在关闭并重新打开 fifo 之前写入不会达到任何 reader 的方法。
内核为整个 read(2)
或 write(2)
调用阻塞了 fifo 的索引节点,因此即使另一个进程在 fifo 上执行另一个 write(2)
也会被阻塞,而你'我不会从第二个作者那里得到关于 reader 的数据(如果你有的话)。喜欢的话可以试试,启动两个writer,看看会发生什么。
$ pru I am the best &
[1] 271
$ pru
Read 2 bytes: I
Wrote 2 bytes: I
Wrote 3 bytes: am
[1]+ Broken pipe pru I am the best <<< this is the kill to the writer process, announced by the shell.
$ _