如何在Shell脚本中周期性向后台C程序的stdin写入数据?
解决方案:实现周期性向C程序的stdin发送数据
你的核心问题是后台运行的C程序和脚本中的cat没有共享stdin流,导致数据无法传递。下面提供两种简单可行的实现方案,同时修正C代码中的潜在问题。
一、修正C代码中的问题
原代码里的fflush(stdin)属于标准未定义行为(fflush仅对输出流有效),且未处理read的错误/EOF情况,同时printf因为行缓冲可能无法实时输出。修改后的代码如下:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> int FnReceiveCharacter(void) { unsigned char c = 0; ssize_t read_len = read(STDIN_FILENO, &c, 1); // 处理读取失败或EOF(比如管道关闭) if (read_len <= 0) { exit(EXIT_SUCCESS); } return c; } int main( ) { while(1) { printf("%c", FnReceiveCharacter()); fflush(stdout); // 强制刷新输出缓冲,确保实时打印 } return 0; }
编译命令不变:cc filename.c -o a.out
二、方案1:使用管道(最简单)
直接将脚本中周期性输出的数据通过管道传递给C程序的stdin,无需后台运行C程序。修改后的shell脚本:
#!/bin/sh clear echo "running the shell command" # 将while循环的输出直接作为a.out的输入 while true do sleep 2 # 输出测试数据,$PPID可替换为你需要的内容 echo "# check $PPID" done | ./a.out
原理
管道|会将前一个命令(while循环)的stdout直接连接到后一个命令(./a.out)的stdin,数据会自动从循环传递到C程序。
三、方案2:使用命名管道(FIFO,适合多进程场景)
如果需要多个进程向C程序发送数据,或者C程序必须后台运行,可以用命名管道实现进程间通信:
#!/bin/sh clear echo "running the shell command" # 创建命名管道(虚拟文件) FIFO_PATH="./my_fifo" mkfifo "$FIFO_PATH" # 让C程序从命名管道读取数据,后台运行 ./a.out < "$FIFO_PATH" & A_OUT_PID=$! # 周期性向命名管道写入数据 while true do sleep 2 echo "# check $PPID" > "$FIFO_PATH" done # 脚本退出时清理资源(杀死C进程、删除管道) trap "kill $A_OUT_PID; rm -f $FIFO_PATH" EXIT
原理
命名管道是一个持久化的虚拟文件,任何进程都可以向它写入数据,同时从它读取的进程会获取这些数据,完美解决不同进程间的stdin共享问题。
内容的提问来源于stack exchange,提问作者Aatif Shaikh
相关产品推荐
相关产品推荐

