当前位置:首页 > 嵌入式 > 嵌入式分享
[导读]在嵌入式Linux开发中,操作GPIO是最常见的需求之一——点亮LED、检测按键、控制继电器。随着内核版本迭代,用户空间操作GPIO的方式经历了三次演变:早期自己写字符设备驱动、中期内核提供的sysfs接口、以及现在推荐的libgpiod。理解这三者的区别,能帮你根据项目阶段做出正确选择。


在嵌入式Linux开发中,操作GPIO是最常见的需求之一——点亮LED、检测按键、控制继电器。随着内核版本迭代,用户空间操作GPIO的方式经历了三次演变:早期自己写字符设备驱动、中期内核提供的sysfs接口、以及现在推荐的libgpiod。理解这三者的区别,能帮你根据项目阶段做出正确选择。

方式一:传统字符设备驱动

这是最底层、最灵活的方式。开发者需要编写内核模块,注册file_operations,实现open/read/write/ioctl,然后在用户空间通过open("/dev/gpio0")操作。

// 内核模块片段

static long gpio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

{

   switch(cmd) {

       case GPIO_SET_DIR_OUT:

           gpio_direction_output(gpio_num, arg);

           break;

       case GPIO_SET_VAL:

           gpio_set_value(gpio_num, arg);

           break;

   }

   return 0;

}


static const struct file_operations fops = {

   .unlocked_ioctl = gpio_ioctl,

};

优点:完全可控,可实现复杂时序(如软件PWM、位带操作);不依赖内核版本变化。

缺点:需要编写和维护内核代码;每次修改都要重新编译模块;调试困难(内核panic可能导致系统崩溃)。

适用场景:对时序要求苛刻、需要原子操作的场合,或现有驱动无法满足需求时。

方式二:sysfs接口

从Linux 2.6开始,内核通过/sys/class/gpio暴露GPIO控制,用户只需shell命令即可操作。

# 导出GPIO

echo 17 > /sys/class/gpio/export

# 设置方向

echo out > /sys/class/gpio/gpio17/direction

# 写值

echo 1 > /sys/class/gpio/gpio17/value

# 读值

cat /sys/class/gpio/gpio17/value

# 取消导出

echo 17 > /sys/class/gpio/unexport

优点:无需编程,脚本即可控制;适合快速原型验证。

缺点:每个GPIO操作涉及多次文件系统读写,延迟大(毫秒级);不支持中断;内核4.8后标记为弃用,部分新平台已移除。

适用场景:教学演示、简单开关控制、调试阶段临时测试。

方式三:libgpiod(新版字符设备)

Linux 4.8引入了基于/dev/gpiochipN的新字符设备接口,配套用户空间库libgpiod。它取代sysfs成为官方推荐方式。

#include <gpiod.h>


struct gpiod_chip *chip = gpiod_chip_open_by_number(0);

struct gpiod_line *line = gpiod_chip_get_line(chip, 17);


// 配置为输出并置高

gpiod_line_request_output(line, "myapp", GPIOD_LINE_ACTIVE_STATE_HIGH);

gpiod_line_set_value(line, 1);


// 读取输入

gpiod_line_request_input(line, "myapp");

int val = gpiod_line_get_value(line);


gpiod_chip_close(chip);

命令行工具也很简洁:

gpioset gpiochip0 17=1

gpioget gpiochip0 18

gpiomon gpiochip0 19  # 监听中断

优点:API清晰,支持批量操作、边缘检测、中断监听;性能优于sysfs;跨内核版本稳定。

缺点:需要安装libgpiod库(Buildroot/Yocto中可选包);相比字符设备仍有一定开销。

适用场景:产品级用户空间GPIO控制,尤其是需要中断响应或高速翻转的场景。

性能对比速览

方式 单次操作延迟(典型值) 中断支持 内核依赖 推荐度

字符设备 ~1μs(取决于实现) 原生支持 需维护模块 特定场景

sysfs ~50-200μs 无 弃用 不推荐新项目

libgpiod ~10-30μs 支持 内核4.8+ ✅首选

实际选型建议

新项目:一律使用libgpiod。它既是内核官方推荐,又能兼顾性能和易用性。

已有sysfs代码迁移:用gpiodetect列出gpiochip编号,替换为libgpiod API即可,改动量不大。

超低延迟需求(如软PWM频率>10kHz):仍需内核字符设备驱动,或者考虑使用PWM子系统。

仅做调试:sysfs依然可用,但请记住它随时可能消失。

⚠️ 注意:某些老旧BSP(如Linux 3.x)可能没有/dev/gpiochip,只能退而求其次使用sysfs。但只要是内核4.8以上,libgpiod就是最优雅的答案。

从字符设备到sysfs再到libgpiod,背后是内核社区对用户空间GPIO接口不断简化和标准化的努力。学会libgpiod,你就掌握了嵌入式Linux GPIO操作的正确姿势。



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除( 邮箱:macysun@21ic.com )。
关闭