You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash脚本循环读取命名管道卡顿(已设超时),求解决建议

问题与解决建议

问题场景

实现Bash脚本与C程序配合的逻辑:创建命名管道并写入初始值0,C程序检测到管道值为0时将其更新为1;Bash脚本持续读取管道值,读到1时终止循环。即使设置了read超时,脚本仍出现卡顿。

卡顿原因分析

  1. 命名管道特性误解:命名管道是字节流管道,数据被读取后就会从管道中移除,无法像文件一样保留内容。脚本中读完值后再写回管道的逻辑会导致读写冲突,引发阻塞。
  2. 重复打开/关闭管道:脚本每次循环都通过< "$pipe_name"重新打开管道读端,C程序也反复打开/关闭管道,频繁的IO操作会触发管道的阻塞特性(管道需要两端同时打开才能完成IO)。
  3. 后台写入进程残留:脚本中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 18:52:35