由问题“如何将进程A的标准输出重定向为进程B的标准输入"引发的思考
若两个进程都是通过bash的同一条命令来启动,可以简单得使用bash的管道来完成。但当进程B是已经在运行状态的程序(如服务器程序),该怎么实现这个功能呢?
为简化讨论,进程A取cat/echo等带输出的待启动程序,进程B对应的程序源码(编译为a.out)如下,
//a.c
#include <stdio.h>
int main() {
int c;
while((c=getc(stdin)) != '@') {
printf("%c, %d\n", c, c);
sleep(1);
}
printf("I am over\n");
return 0;
}
思路1:直接往进程B的proc/pid_of_B/fd/0
写数据
echo zwl@@ > /proc/`pidof a.out`/fd/0
实测下来发现,进程B的输出能显式写入的字符序列,但并没有进程B的读操作getc
。真实输入终端(键盘)产生字节序列,并将序列写到内存,然后给cpu发送中断信号,触发操作系统的读取处理程序,这里直接写没有后半部分,所以效果不理想。
思路2: 使用正常的文件
进程B将一个正常文件作为输入,进程A往这个文件写入内容。设文件名为aa。
实际测试下来发现两个问题:一是,getc读到文件的末尾会非阻塞式返回EOF,这和stdin中没内容时,read处于阻塞等待状态不同;二是,当B进程移动到aa文件的末尾时,echo zwl@@ > aa
,B进程读不到写入的内容,必须以追加的方式向aa添加字节,即echo zwl@@ >> aa
。
思路3: 使用namedpipe
namedpipe是一种先进先出的文件,相比传统的pipe,namedpipe生存周期同操作系统,即不重启机器都在,而传统的pipe同产生pipe的进程生命周期。
使用下面的脚本bash命令可以向进程B的标准输入传递字节序列"zwl@@"。
touch zwl_pipe
sudo gdb attach `pidof a.out` << EOF
set confirm off
call (void*)dlopen("./libRSIWF.so",2)
call replace_fd_with_norm_file("zwl_pipe", 0)
q
EOF
echo zwl@@ > zwl_pipe
思路4:使用虚拟终端
思路4和思路5除了需要对进程B处理,还需要对进程A处理。思路是将一个管段的两头(两个fd),一个和进程A的stdout相连,另一个和进程
参考https://linux.die.net/man/4/ptmx.
先用gdb attach到进程A(cat),修改其stdout
sudo gdb attach `pidof cat` << EOF
set confirm off
call (void*)dlopen("./libRSIWF.so",2)
call create_pseudo_master_file_and_bind_to_stdout()
q
EOF
ptsname的接口在c程序中用经常会出现问题,最好自己申请字符串内存,然后使用ptsname_r
。
create_pseudo_master_file_and_bind_to_stdout()
打印的输出在原进程B的标准输出,不在gdb所在的进程。
sudo gdb attach `pidof a.out` << EOF
set confirm off
call (void*)dlopen("./libRSIWF.so",2)
call replace_fd_with_norm_file("/dev/pts/5",0)
q
EOF
上面的/dev/pts/5
为对cat打桩看到的输出
思路5: 使用socket
在进程B中启动一个socket, acceptY一个来自进程A的socket连接,将进程B中socket和其标准输入绑定,将进程A中的socket和其标准输出绑定。
首先在进程B中使用下面的bash脚本,此时a.out处于等待进程A的socket连接的状态。
sudo gdb attach `pidof a.out` << EOF
set confirm off
call (void*)dlopen("./libRSIWF.so",2)
call (int)replace_fd_with_a_connected_port(8081,0)
EOF
在另外一个gdb中attach进程A,我们使用下面的脚本和a.out取得连接
sudo gdb attach `pidof cat` << EOF
set confirm off
call (void*)dlopen("./libRSIWF.so",2)
call (int)replace_fd_with_a_host_and_port("localhost", 8081, 1)
q
EOF
libRSIWF.so的源码见https://gitlab.com/1530306732/notes/-/tree/replace_std_io_with_file?ref_type=heads
标签:pidof,zwl,重定向,attach,标准,gdb,进程,out From: https://www.cnblogs.com/zwlwf/p/17473545.html