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

Rust中使用nix库SIGALARM实现进程通信遇阻塞问题求助

Rust中使用nix库alarm功能实现进程间通信的问题

我尝试通过SIGALRM让两个子进程每2秒互相通信,并通过管道返回数据,但运行代码后程序一直处于等待状态,看不到预期消息。以下是我的代码:

use nix::sys::wait::wait;
use nix::unistd::ForkResult::{Child, Parent};
use nix::unistd::fork;
use nix::unistd::{alarm, pause};
use nix::sys::signal::*;
use std::io::prelude::*;

extern fn signal_handler(_: nix::libc::c_int) {}

fn set_alarm(sec: i32) {
    alarm::set(sec.try_into().unwrap());
}

fn main() {
    let (mut reader_2, mut writer_2) = os_pipe::pipe().unwrap();
    unsafe { 
        sigaction(
            Signal::SIGALRM, 
            &SigAction::new(
                SigHandler::Handler(signal_handler), 
                SaFlags::empty(), 
                SigSet::empty())
            ).unwrap(); 
    }
    let pid = fork();
    match pid.expect("Error during creating child") {
        Parent { child } => {
            drop(writer_2);
            let pid_2 = fork();
            match pid_2.expect("Error creating child 2") {
                Parent { child } => {}
                Child => {
                    let mut data: [u8;2] = [0;2];
                    for _ in 1..=10 {
                        set_alarm(2);
                        pause();
                        reader_2.read_exact(&mut data).unwrap();
                        println!("Data from C1, {}", std::str::from_utf8(&data).unwrap());
                    }
                }
            }
        }

        Child => {
            drop(reader_2);
            for _ in 1..=10 {
                pause();
                println!("here");
                writer_2.write("C1".as_bytes()).unwrap();
            }
        }
    }
    wait().unwrap();
}

问题分析与修复方案

核心问题点

  • 第一个子进程(C1)未设置闹钟:C1的循环中只有pause(),从未调用set_alarm(),导致它永远阻塞等待信号,无法往管道写入数据,进而让第二个子进程(C2)读管道时阻塞。
  • 父进程等待逻辑缺失:原代码只调用一次wait(),无法保证等待两个子进程全部结束,可能导致父进程提前退出。
  • alarm调用错误:nix库中alarm是直接调用的函数,而非alarm::set()模块方法。
  • 管道句柄提前释放:父进程提前drop(writer_2)会影响C1的管道写入句柄有效性。

修正后的代码

use nix::sys::wait::waitpid;
use nix::unistd::ForkResult::{Child, Parent};
use nix::unistd::{fork, Pid};
use nix::unistd::{alarm, pause};
use nix::sys::signal::*;
use std::io::prelude::*;

extern fn signal_handler(_: nix::libc::c_int) {}

fn set_alarm(sec: u32) {
    alarm(sec);
}

fn main() {
    let (mut reader_2, mut writer_2) = os_pipe::pipe().unwrap();
    unsafe { 
        sigaction(
            Signal::SIGALRM, 
            &SigAction::new(
                SigHandler::Handler(signal_handler), 
                SaFlags::SA_RESTART,
                SigSet::empty())
            ).unwrap(); 
    }
    let pid = fork().expect("Error during creating child");
    match pid {
        Parent { child: c1_pid } => {
            let pid_2 = fork().expect("Error creating child 2");
            match pid_2 {
                Parent { child: c2_pid } => {
                    waitpid(c1_pid, None).unwrap();
                    waitpid(c2_pid, None).unwrap();
                }
                Child => {
                    drop(writer_2);
                    let mut data: [u8;2] = [0;2];
                    for _ in 1..=10 {
                        set_alarm(2);
                        pause();
                        if reader_2.read_exact(&mut data).is_ok() {
                            println!("Data from C1: {}", std::str::from_utf8(&data).unwrap());
                        }
                    }
                }
            }
        }

        Child => {
            drop(reader_2);
            for _ in 1..=10 {
                set_alarm(2);
                pause();
                println!("C1 sending data...");
                writer_2.write_all("C1".as_bytes()).unwrap();
                writer_2.flush().unwrap();
            }
        }
    }
}

关键修正说明

  1. 给C1添加闹钟设置:确保C1每2秒被SIGALRM唤醒,执行管道写入操作。
  2. 修正alarm调用:使用nix库原生的alarm()函数替代错误的alarm::set()。
  3. 完善父进程等待逻辑:用waitpid分别等待两个子进程,保证所有子进程执行完毕。
  4. 调整管道句柄释放时机:在对应的子进程中释放不需要的管道句柄,避免父进程提前释放影响子进程。
  5. 添加SA_RESTART标志:让被信号中断的系统调用自动重启,提升程序稳定性。
  6. 使用write_all和flush:确保数据完整写入管道并刷新缓冲区,避免数据滞留。

内容的提问来源于stack exchange,提问作者danixl30 ct

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 12:25:19