Rust系统进程信息库darwin-libproc-sys的使用:macOS平台下高效获取进程状态与系统调用信息

Rust系统进程信息库darwin-libproc-sys的使用:macOS平台下高效获取进程状态与系统调用信息

darwin-libproc-sys是一个为macOS平台提供的低级Rust绑定库,用于访问libproc系统库的功能。

特性

Latest Version Minimum rustc version Platforms supported Unsafe

该库提供对macOS XNU内核4903.221.2版本中libproc功能的非安全低级绑定。

安装

在项目目录中运行以下Cargo命令:

cargo add darwin-libproc-sys

或直接在Cargo.toml中添加:

darwin-libproc-sys = "0.2.0"

示例代码

以下是一个使用darwin-libproc-sys获取进程信息的完整示例:

// 导入必要的库
use darwin_libproc_sys::proc::*;
use std::mem;
use std::ptr;

fn main() {
    // 获取当前进程ID
    let pid = unsafe { proc_pidinfo(proc_selfpid(), PROC_PIDLISTTHREADS, 0, ptr::null_mut(), 0) };
    
    if pid <= 0 {
        eprintln!("Failed to get process info");
        return;
    }

    // 获取进程名称
    let mut name_buffer: [u8; 256] = [0; 256];
    let result = unsafe {
        proc_name(proc_selfpid(), name_buffer.as_mut_ptr() as *mut libc::c_void, name_buffer.len() as u32)
    };

    if result > 0 {
        let process_name = String::from_utf8_lossy(&name_buffer[..result as usize]);
        println!("Process name: {}", process_name);
    } else {
        eprintln!("Failed to get process name");
    }

    // 获取线程信息
    let thread_count = unsafe { proc_pidinfo(proc_selfpid(), PROC_PIDLISTTHREADS, 0, ptr::null_mut(), 0) };
    println!("Thread count: {}", thread_count);
}

完整示例代码

以下是一个更完整的示例,展示如何获取多个进程信息:

use darwin_libproc_sys::proc::*;
use std::{ptr, mem};

fn main() {
    // 获取所有进程ID
    let mut pids = vec![0; 2048];
    let pid_count = unsafe {
        proc_listpids(PROC_ALL_PIDS, 0, pids.as_mut_ptr() as *mut libc::c_void, 
                     (pids.len() * mem::size_of::<u32>()) as i32)
    } / mem::size_of::<u32>() as i32;

    if pid_count <= 0 {
        eprintln!("Failed to get process list");
        return;
    }

    println!("Found {} processes", pid_count);

    // 遍历前10个进程获取信息
    for &pid in pids.iter().take(10) {
        if pid == 0 {
            continue;
        }

        // 获取进程名称
        let mut name_buffer = [0u8; 256];
        let name_len = unsafe {
            proc_name(pid, name_buffer.as_mut_ptr() as *mut libc::c_void, name_buffer.len() as u32)
        };

        if name_len > 0 {
            let name = String::from_utf8_lossy(&name_buffer[..name_len as usize]);
            println!("PID: {}, Name: {}", pid, name);
        } else {
            println!("PID: {} (name unavailable)", pid);
        }

        // 获取进程路径
        let mut path_buffer = [0u8; libc::PATH_MAX as usize];
        if unsafe { proc_pidpath(pid, path_buffer.as_mut_ptr() as *mut libc::c_void, path_buffer.len() as u32) } > 0 {
            let path = String::from_utf8_lossy(&path_buffer);
            println!("  Path: {}", path.trim_end_matches('\0'));
        }

        // 获取线程数
        let thread_count = unsafe { proc_pidinfo(pid, PROC_PIDLISTTHREADS, 0, ptr::null_mut(), 0) };
        println!("  Threads: {}", thread_count);
    }
}

文档

完整API文档可在文档网站查看。

许可证

该项目采用双许可证:

  • Apache License 2.0
  • MIT license

注意事项

  1. 该库提供的是非安全(unsafe)FFI绑定
  2. 仅适用于macOS平台
  3. 如需更安全的包装,可参考darwin-libproc crate

所有权

主要维护者:svartalf


1 回复

Rust系统进程信息库darwin-libproc-sys使用指南

简介

darwin-libproc-sys是一个Rust库,提供了对macOS系统libproc库的绑定,允许开发者在macOS平台下高效获取进程状态和系统调用信息。这个库特别适合需要监控或管理系统进程的应用程序开发。

主要功能

  • 获取进程列表
  • 查询进程信息(名称、PID、状态等)
  • 获取进程路径
  • 查询线程信息
  • 获取系统调用信息

安装

在Cargo.toml中添加依赖:

[dependencies]
darwin-libproc-sys = "0.1"

基本使用方法

1. 获取所有进程ID

use darwin_libproc_sys::proc;

fn main() {
    let pids = proc::listpids(proc::ProcType::ProcAllPIDS, 0).unwrap();
    println!("Running processes: {:?}", pids);
}

2. 获取进程信息

use darwin_libproc_sys::proc;

fn main() {
    let pid = 1234; // 替换为你想查询的PID
    let info = proc::pidinfo::<proc::ProcTaskAllInfo>(pid, 0).unwrap();
    println!("Process {} info: {:?}", pid, info);
}

3. 获取进程路径

use darwin_libproc_sys::proc;

fn main() {
    let pid = 1234; // 替换为你想查询的PID
    let path = proc::pidpath(pid).unwrap();
    println!("Process {} path: {}", pid, path);
}

4. 获取进程名称

use darwin_libproc_sys::proc;

fn main() {
    let pid = 1234; // 替换为你想查询的PID
    let name = proc::name(pid).unwrap();
    println!("Process {} name: {}", pid, name);
}

高级用法

获取线程信息

use darwin_libproc_sys::proc;

fn main() {
    let pid = 1234; // 替换为你想查询的PID
    let threads = proc::listpidthreads(pid).unwrap();
    println!("Threads for process {}: {:?}", pid, threads);
    
    for tid in threads {
        let thread_info = proc::threadinfo(pid, tid).unwrap();
        println!("Thread {} info: {:?}", tid, thread_info);
    }
}

监控进程状态变化

use darwin_libproc_sys::proc;
use std::thread;
use std::time::Duration;

fn monitor_process(pid: i32) {
    loop {
        match proc::pidinfo::<proc::ProcTaskAllInfo>(pid, 0) {
            Ok(info) => {
                println!("Process {} status: {:?}", pid, info.pbsd.pbi_status);
            },
            Err(e) => {
                println!("Error or process ended: {}", e);
                break;
            }
        }
        thread::sleep(Duration::from_secs(1));
    }
}

完整示例Demo

以下是一个结合多个功能的完整示例,演示如何监控特定进程的状态变化:

use darwin_libproc_sys::proc;
use std::thread;
use std::time::Duration;

fn main() {
    // 获取当前所有进程列表
    let all_pids = proc::listpids(proc::ProcType::ProcAllPIDS, 0).unwrap();
    println!("当前系统进程数: {}", all_pids.len());

    // 获取第一个进程的详细信息作为示例
    if let Some(&pid) = all_pids.first() {
        println!("\n监控进程 {} 的详细信息:", pid);
        
        // 获取并显示进程名称
        if let Ok(name) = proc::name(pid) {
            println!("进程名称: {}", name);
        }
        
        // 获取并显示进程路径
        if let Ok(path) = proc::pidpath(pid) {
            println!("进程路径: {}", path);
        }
        
        // 获取并显示进程完整信息
        if let Ok(info) = proc::pidinfo::<proc::ProcTaskAllInfo>(pid, 0) {
            println!("进程状态: {:?}", info.pbsd.pbi_status);
            println!("进程优先级: {}", info.ptinfo.pti_priority);
        }
        
        // 监控进程状态变化
        println!("\n开始监控进程状态变化...");
        monitor_process(pid);
    }
}

fn monitor_process(pid: i32) {
    let mut prev_status = None;
    
    loop {
        match proc::pidinfo::<proc::ProcTaskAllInfo>(pid, 0) {
            Ok(info) => {
                // 只在状态变化时打印
                if prev_status != Some(info.pbsd.pbi_status) {
                    println!("[PID {}] 状态变化: {:?}", pid, info.pbsd.pbi_status);
                    prev_status = Some(info.pbsd.pbi_status);
                }
            },
            Err(e) => {
                println!("错误或进程已结束: {}", e);
                break;
            }
        }
        thread::sleep(Duration::from_secs(1));
    }
}

注意事项

  1. 需要macOS系统支持
  2. 某些操作可能需要root权限
  3. 错误处理很重要,因为进程可能在任何时候终止
  4. 频繁查询可能会影响系统性能

性能建议

  • 批量获取信息而不是单个查询
  • 缓存不常变化的信息
  • 合理设置轮询间隔

这个库为macOS系统进程监控和管理提供了强大的底层支持,可以用于开发系统监控工具、调试工具或任务管理器等应用。

回到顶部