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

在Rust中使用nix crate实现C代码ioctl(fd, UI_SET_EVBIT, EV_KEY)等价操作的问题

在Rust中使用nix crate实现C代码ioctl(fd, UI_SET_EVBIT, EV_KEY)等价操作的问题

刚接触Rust和nix crate的话,确实会因为C风格的ioctl到Rust的映射有点摸不着头脑,我来帮你解决这个问题:

首先,C里的ioctl(fd, UI_SET_EVBIT, EV_KEY)本质是向uinput设备传递一个整数值(EV_KEY的枚举值),用来启用按键事件类型。在nix crate里,并没有预定义所有uinput相关的ioctl,所以我们需要自己用nix提供的宏来生成对应的ioctl调用函数。

步骤1:定义UI_SET_EVBIT对应的ioctl函数

nix提供了一系列ioctl宏来处理不同类型的参数传递,这里我们用ioctl_write_int!宏——因为这个ioctl是向内核写入一个整数值。你需要根据内核头文件里的定义来填魔数和命令号:

use nix::ioctl_write_int;
use libc;
use nix::fcntl::{O_WRONLY, O_NONBLOCK};
use nix::fs::open;
use std::os::unix::io::AsRawFd;

// 对应内核中#define UI_SET_EVBIT _IOW('U', 1, int)的定义
// 魔数是b'U',命令号是1,参数为整数类型
ioctl_write_int!(ui_set_evbit, b'U', 1);

步骤2:调用定义好的ioctl函数

打开uinput设备文件后,就可以调用这个函数来设置EV_KEY位了,注意ioctl调用是unsafe的,因为它直接和内核交互,Rust无法保证操作的安全性:

fn main() {
    // 打开uinput设备,权限和C里的open保持一致
    let uinput_fd = match open("/dev/uinput", O_WRONLY | O_NONBLOCK, nix::sys::stat::Mode::empty()) {
        Ok(fd) => fd,
        Err(e) => {
            eprintln!("Failed to open uinput device: {}", e);
            return;
        }
    };

    // 调用UI_SET_EVBIT设置EV_KEY位
    let ev_key = libc::EV_KEY as i32;
    unsafe {
        if let Err(e) = ui_set_evbit(uinput_fd.as_raw_fd(), ev_key) {
            eprintln!("Failed to set EV_KEY event bit: {}", e);
        }
    }
}

关键说明

  • 魔数和命令号必须和内核定义一致:内核中UI_SET_EVBIT的定义是_IOW('U', 1, int),所以我们用b'U'作为魔数,1作为命令号,如果你的内核版本里命令号有差异,需要对应调整。
  • 依赖补充:确保你的Cargo.toml里添加了nix和libc依赖,这样才能使用对应的宏和常量定义:
[dependencies]
nix = "0.27"
libc = "0.2"
  • 错误处理:实际项目中记得完善错误处理逻辑,比如设备打开失败、ioctl调用失败的情况。

备注:内容来源于stack exchange,提问作者S. Velik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 07:53:13