Bash脚本循环读取命名管道卡顿(已设超时),求解决建议
问题与解决建议
问题场景
实现Bash脚本与C程序配合的逻辑:创建命名管道并写入初始值0,C程序检测到管道值为0时将其更新为1;Bash脚本持续读取管道值,读到1时终止循环。即使设置了read超时,脚本仍出现卡顿。
卡顿原因分析
- 命名管道特性误解:命名管道是字节流管道,数据被读取后就会从管道中移除,无法像文件一样保留内容。脚本中读完值后再写回管道的逻辑会导致读写冲突,引发阻塞。
- 重复打开/关闭管道:脚本每次循环都通过
< "$pipe_name"重新打开管道读端,C程序也反复打开/关闭管道,频繁的IO操作会触发管道的阻塞特性(管道需要两端同时打开才能完成IO)。 - 后台写入进程残留:脚本中
echo "$STOP_FH_LOGS" > "$pipe_name" &会创建后台进程,若管道读端未及时打开,后台进程会一直阻塞,导致资源占用和脚本卡顿。
解决步骤
- 用变量维护状态,而非依赖管道存储:管道仅用作进程间的通知机制,脚本内部用变量保存当前状态,无需将值写回管道。
- 保持管道读写端持续打开:脚本提前打开管道的读写端并保持打开,避免每次循环重新打开导致的阻塞。
- 调整C程序的管道操作逻辑:C程序无需反复读取管道,只需在检测到初始状态后写入一次通知即可;同时确保写入操作不会因管道未打开而阻塞。
- 移除不必要的后台写入操作:避免后台进程残留引发的阻塞问题。
修改后的Bash脚本
#!/bin/bash pipe_name="/tmp/my_pipe" initial_value="0" # 创建命名管道(如果不存在) if [ ! -p "$pipe_name" ]; then mkfifo "$pipe_name" fi # 提前打开管道的读写端,保持打开状态以避免阻塞 exec 3<> "$pipe_name" # 写入初始值 echo -n "$initial_value" >&3 STOP_FH_LOGS="$initial_value" while true; do # 从管道读取1个字符,设置1秒超时 if read -t 1 -n 1 new_value <&3; then STOP_FH_LOGS=$new_value if [ "$STOP_FH_LOGS" = "1" ]; then echo "Value changed to 1" break elif [ "$STOP_FH_LOGS" = "0" ]; then echo "Condition still 0" # 无需写回管道,仅需等待C程序的更新 else echo "New STOP_FH_LOGS error value: $STOP_FH_LOGS" fi else echo "Timeout or no data read" fi done # 关闭管道文件描述符 exec 3>&- # 清理管道 rm -f "$pipe_name"
修改后的C代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #define PIPE_NAME "/tmp/my_pipe" #define NEW_VALUE "1" int main() { char buffer[2]; int pipe_fd; // 打开管道读端,等待脚本写入初始值 pipe_fd = open(PIPE_NAME, O_RDONLY); if (pipe_fd == -1) { perror("Failed to open pipe for reading"); exit(EXIT_FAILURE); } // 读取初始值 ssize_t num_read = read(pipe_fd, buffer, 1); if (num_read == -1) { perror("Pipe read error"); close(pipe_fd); exit(EXIT_FAILURE); } buffer[num_read] = '\0'; close(pipe_fd); // 检测到初始值0,写入更新值1 if (strcmp(buffer, "0") == 0) { int write_fd = open(PIPE_NAME, O_WRONLY); if (write_fd == -1) { perror("Failed to open pipe for writing"); exit(EXIT_FAILURE); } write(write_fd, NEW_VALUE, strlen(NEW_VALUE)); close(write_fd); } return 0; }
内容的提问来源于stack exchange,提问作者Abhir Raj Shrivastava
相关产品推荐
相关产品推荐

