我有这个简单的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 ...
我的问题如下:我希望操作系统在执行write()调用后阻止程序执行。 作为一个简单的非root用户,是否有可能创build这样的场景? 请注意,我不能改变任何程序代码。
我的直觉告诉我应该,但是我却找不到解决办法。 想象一下,write()会写入一个文件描述符,并返回给一个没有缓冲的字符设备。 这样的设备,不会强制写入()来阻止?
write
系统调用将数据复制到与文件描述符关联的内核缓冲区中。 只要有可能进行缓冲,呼叫就不会被阻塞。 但是,如果你写足够的数据到一个缓慢的输出设备,那么最终write
将会阻塞。
写几个字节来阻塞是件有些工作。 以下是一种方法:
首先,创建一个命名管道:
mkfifo /tmp/the_fifo
任何试图打开 /tmp/the_fifo
进行写入的操作都会阻塞,直到某个进程打开fifo进行读取。 你可以打开阅读的fifo,而不需要阅读任何东西,如:
sleep 1000 < /tmp/the_fifo &
现在你可以填充fifo缓冲区了:
yes > /tmp/the_fifo &
在这一点上,当你的程序试图写入/tmp/fifo
时,你的程序应该被阻塞。
完成后,不要忘记杀死后台进程并删除命名管道。
如果你写入管道,没有人读取管道,它最终会填满。 我可能是错的,默认的Linux管道大小是64KB。
尝试将应用程序的输出传输到从不读取其标准输入的应用程序中,如下所示:
./hw | sleep 1000
sleep
永远不会读取其标准输入,这样你就可以很容易地填写管道。