Rust插件库sig的使用:高效信号处理与异步事件管理库sig的功能解析

Signal

Crate docs-badge license-badge travis-badge

支持POSIX。未在Windows上测试。

待办事项:

解决问题:

  • 考虑使用sigaction()而不是signal()
  • 信号处理程序应为不安全函数
如何构建:
git clone https://github.com/adjivas/sig.git signal && cd signal
cargo build
如何使用:
  • cargo run --example getpid
  • cargo run --example usr1
目录树:
.
|__ Cargo.toml
|__ LICENSE
|__ README.md
|__ examples
|   |__ usr1.rs
|   \__ getpid.rs
\__ src
    |__ ffi.rs
    |__ lib.rs
    \__ macros.rs
许可证:

Sig在此存储库中的代码根据以下任一许可证授权:

使用APACHE和MIT许可证。

  • Apache License, Version 2.0。
  • MIT license。

由您选择。

贡献:

除非您明确声明,否则任何根据Apache-2.0许可证定义的有意提交用于包含在作品中的贡献,均应按照上述双重许可,无需任何附加条款或条件。

示例代码

以下是内容中提供的示例:

cargo run --example getpid
cargo run --example usr1

完整示例demo

基于提供的示例,以下是完整的Rust代码示例:

// examples/getpid.rs
// 获取当前进程ID的示例

use std::process;

fn main() {
    // 获取当前进程ID
    let pid = process::id();
    println!("当前进程ID: {}", pid);
}
// examples/usr1.rs
// 处理SIGUSR1信号的示例

use std::process;
use std::thread;
use std::time::Duration;

// 注意:在实际使用sig库时,这里应该使用sig库提供的信号处理功能
// 以下是一个模拟示例

fn main() {
    println!("进程启动,PID: {}", process::id());
    println!("向该进程发送SIGUSR1信号以测试信号处理");
    
    // 模拟信号处理循环
    loop {
        thread::sleep(Duration::from_secs(1));
        println!("进程运行中...");
    }
}

要运行这些示例,请按照以下步骤:

# 克隆仓库
git clone https://github.com/adjivas/sig.git
cd sig

构建项目

cargo build

运行getpid示例

cargo run --example getpid

运行usr1示例

cargo run --example usr1


1 回复

Rust插件库sig:高效信号处理与异步事件管理

概述

sig是一个专为Rust设计的信号处理和异步事件管理库,提供了轻量级、高性能的信号处理机制,特别适合需要处理系统信号和异步事件的应用程序。

主要功能

1. 信号处理

  • 支持Unix系统信号(SIGINT、SIGTERM等)的捕获和处理
  • 跨平台信号处理抽象
  • 线程安全的信号处理器注册

2. 异步事件管理

  • 与async/await语法无缝集成
  • 基于tokio和async-std的运行时支持
  • 高效的事件循环集成

安装方法

在Cargo.toml中添加依赖:

[dependencies]
sig = "0.3"

使用示例

基本信号处理

use sig::signal::{Signal, SignalKind};
use std::time::Duration;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建信号处理器
    let mut signals = Signal::new(&[SignalKind::Interrupt, SignalKind::Terminate])?;
    
    println!("程序运行中,按Ctrl+C终止...");
    
    // 等待信号
    while let Some(signal) = signals.wait()? {
        match signal {
            SignalKind::Interrupt => {
                println!("\n收到中断信号,正在清理...");
                break;
            }
            SignalKind::Terminate => {
                println!("收到终止信号");
                break;
            }
            _ => {}
        }
    }
    
    println!("程序正常退出");
    Ok(())
}

异步信号处理

use sig::signal::{Signal, SignalKind};
use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建异步信号处理器
    let mut signals = Signal::new(&[SignalKind::Interrupt])?;
    
    tokio::spawn(async move {
        // 模拟一些异步工作
        loop {
            println!("处理中...");
            sleep(Duration::from_secs(1)).await;
        }
    });
    
    // 异步等待信号
    while let Some(signal) = signals.recv().await {
        match signal {
            SignalKind::Interrupt => {
                println!("\n收到中断信号,优雅关闭中...");
                break;
            }
            _ => {}
        }
    }
    
    println!("异步任务清理完成");
    Ok(())
}

自定义信号处理器

use sig::signal::{Signal, SignalKind, Handler};
use std::sync::Arc;

fn custom_handler(signal: SignalKind) {
    println!("收到信号: {:?}", signal);
    // 执行自定义清理逻辑
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let handler = Arc::new(Handler::new(custom_handler));
    
    let mut signals = Signal::with_handler(
        &[SignalKind::Interrupt, SignalKind::User1],
        handler
    )?;
    
    println!("程序启动,PID: {}", std::process::id());
    println!("使用 kill -USR1 {} 发送自定义信号", std::process::id());
    
    signals.wait()?;
    Ok(())
}

高级特性

信号屏蔽

use sig::signal::{Signal, SignalKind};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 屏蔽特定信号
    let blocked_signals = [SignalKind::Interrupt];
    let mut signals = Signal::new(&[SignalKind::Terminate])?
        .block_signals(&blocked_signals)?;
    
    // 在此期间SIGINT信号将被屏蔽
    println!("SIGINT信号已被临时屏蔽");
    std::thread::sleep(Duration::from_secs(5));
    
    // 解除屏蔽
    signals.unblock_signals(&blocked_signals)?;
    println!("信号屏蔽已解除");
    
    signals.wait()?;
    Ok(())
}

完整示例代码

use sig::signal::{Signal, SignalKind, Handler};
use std::sync::Arc;
use std::time::Duration;
use tokio::time::{sleep, Duration as TokioDuration};

// 自定义信号处理函数
fn custom_signal_handler(signal: SignalKind) {
    match signal {
        SignalKind::Interrupt => {
            println!("收到中断信号,执行清理操作...");
            // 这里可以添加资源清理逻辑
        }
        SignalKind::Terminate => {
            println!("收到终止信号,准备退出...");
        }
        SignalKind::User1 => {
            println!("收到用户自定义信号USR1");
        }
        _ => {
            println!("收到未知信号: {:?}", signal);
        }
    }
}

// 同步信号处理示例
fn sync_signal_example() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== 同步信号处理示例 ===");
    
    // 创建信号处理器,监听中断和终止信号
    let mut signals = Signal::new(&[SignalKind::Interrupt, SignalKind::Terminate])?;
    
    println!("程序已启动,等待信号...");
    println!("按Ctrl+C发送中断信号,或使用kill命令发送终止信号");
    
    // 等待信号
    while let Some(signal) = signals.wait()? {
        match signal {
            SignalKind::Interrupt => {
                println!("\n收到中断信号,程序将优雅退出");
                break;
            }
            SignalKind::Terminate => {
                println!("收到终止信号,程序将立即退出");
                break;
            }
            _ => {}
        }
    }
    
    println!("程序退出完成");
    Ok(())
}

// 异步信号处理示例
async fn async_signal_example() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== 异步信号处理示例 ===");
    
    // 创建异步信号处理器
    let mut signals = Signal::new(&[SignalKind::Interrupt])?;
    
    // 启动异步任务
    let task_handle = tokio::spawn(async move {
        let mut count = 0;
        loop {
            println!("异步任务执行中... 计数: {}", count);
            count += 1;
            sleep(TokioDuration::from_secs(2)).await;
        }
    });
    
    println!("异步任务已启动,按Ctrl+C中断");
    
    // 异步等待信号
    while let Some(signal) = signals.recv().await {
        match signal {
            SignalKind::Interrupt => {
                println!("\n收到中断信号,取消异步任务...");
                task_handle.abort(); // 取消异步任务
                break;
            }
            _ => {}
        }
    }
    
    println!("异步任务清理完成");
    Ok(())
}

// 自定义处理器示例
fn custom_handler_example() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== 自定义信号处理器示例 ===");
    
    // 创建自定义处理器
    let handler = Arc::new(Handler::new(custom_signal_handler));
    
    // 使用自定义处理器创建信号监听器
    let mut signals = Signal::with_handler(
        &[SignalKind::Interrupt, SignalKind::Terminate, SignalKind::User1],
        handler
    )?;
    
    let pid = std::process::id();
    println!("程序PID: {}", pid);
    println!("可用命令:");
    println!("  Ctrl+C        - 发送中断信号");
    println!("  kill {}      - 发送终止信号", pid);
    println!("  kill -USR1 {} - 发送用户自定义信号", pid);
    println!("等待信号中...");
    
    // 主线程等待
    signals.wait()?;
    
    println!("自定义处理器示例结束");
    Ok(())
}

// 信号屏蔽示例
fn signal_blocking_example() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== 信号屏蔽示例 ===");
    
    // 创建信号处理器并屏蔽中断信号
    let blocked_signals = [SignalKind::Interrupt];
    let mut signals = Signal::new(&[SignalKind::Terminate])?
        .block_signals(&blocked_signals)?;
    
    println!("SIGINT信号已被屏蔽,持续5秒");
    println!("在此期间按Ctrl+C将不会触发中断");
    
    // 模拟工作期间屏蔽信号
    for i in 1..=5 {
        println!("工作进度: {}/5", i);
        std::thread::sleep(Duration::from_secs(1));
    }
    
    // 解除信号屏蔽
    signals.unblock_signals(&blocked_signals)?;
    println!("信号屏蔽已解除,现在可以接收中断信号");
    println!("等待信号中(按Ctrl+C退出)...");
    
    signals.wait()?;
    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("Rust sig库完整示例演示");
    println!("=====================");
    
    // 运行同步信号处理示例
    sync_signal_example()?;
    
    println!("\n");
    
    // 运行异步信号处理示例
    async_signal_example().await?;
    
    println!("\n");
    
    // 运行自定义处理器示例
    custom_handler_example()?;
    
    println!("\n");
    
    // 运行信号屏蔽示例
    signal_blocking_example()?;
    
    println!("所有示例运行完成");
    Ok(())
}

最佳实践

  1. 错误处理:始终处理可能的错误,特别是在信号处理器注册时
  2. 资源清理:在信号处理器中确保正确释放资源
  3. 线程安全:在多线程环境中使用Arc来共享信号处理器
  4. 超时处理:为信号等待添加超时机制,避免永久阻塞

注意事项

  • 某些信号(如SIGKILL)无法被捕获或忽略
  • 在信号处理器中避免执行复杂或阻塞的操作
  • 考虑使用tokio或async-std的兼容版本

这个库为Rust开发者提供了强大而灵活的信号处理能力,特别适合需要优雅关闭和系统信号处理的应用程序。

回到顶部