创建 write() 阻塞的场景

Create a scenario where write() is blocking

我得到了这个简单的 C 程序:

#include <stdio.h>

int main (int argc, char *argv[])
{
  printf ("Hello, world\n");

  return 0;
}

如果我跟踪编译后的程序 printf() 变成 write():

$ strace ./hw > x
execve("./hw", ["./hw"], [/* 19 vars */]) = 0
...
write(1, "Hello, world\n", 13)          = 13
...

我的问题如下:我希望 OS 在执行 write() 调用后阻止程序执行。作为一个简单的非 root 用户,是否有可能创建这样的场景?请注意,我无法对程序代码进行任何更改。

我的直觉告诉我应该这样做,但我无法找到解决方案。想象一下 write() 将写入一个文件描述符,引用一个无缓冲的字符设备。这样的设备,它不会强制write()阻塞吗?

write 系统调用将数据复制到与文件描述符关联的内核缓冲区中。只要可以缓冲,调用就不会阻塞。但是如果你向一个慢速输出设备写入足够多的数据,那么最终 write 会阻塞。

将几个字节写入块是一项艰巨的工作。这是一种方法:

首先,创建命名管道:

mkfifo /tmp/the_fifo

任何 open /tmp/the_fifo 写入的尝试都将阻塞,直到某个进程打开 fifo 进行读取。您可以打开 fifo 进行阅读而不阅读任何内容,例如:

sleep 1000 < /tmp/the_fifo &

现在您可以填充 fifo 缓冲区了:

yes > /tmp/the_fifo &

此时,您的程序在尝试写入 /tmp/fifo 时应该会阻塞。

完成后,不要忘记终止后台进程并删除命名管道。

如果您写入一个管道,但没有人读取该管道,它最终会填满。我可能错了,默认的 Linux 管道大小是 64KB。

尝试将应用程序的输出通过管道传输到从不读取其标准输入的应用程序中,如下所示:

./hw | sleep 1000

sleep 从不读取它的标准输入,这样你就可以很容易地填充管道。