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

libgpiod C++ 2.1.x请求GPIO线路报错:设备或资源忙

问题:libgpiod请求GPIO线路提示“Device or resource busy”

基于libgpiod的C++示例编写了监听多路GPIO的类,代码如下:

#include <stdlib.h>
#include <iostream>
#include <thread>
#include <chrono>
#include <vector>

#include <cstdlib>
#include <gpiod.hpp>
#include <iomanip>
#include <iostream>
#include <filesystem>

#include "gpiod.hpp"

#define GPIO_PORT_1_LINE 0
#define GPIO_PORT_2_LINE 1
#define GPIO_PORT_3_LINE 5
#define GPIO_PORT_4_LINE 6

#define GPIO_CHIP_NAME "/dev/gpiochip0"

IO::IO()
{
    std::cout << "IO constructor" << std::endl;
}

IO::~IO()
{
    std::cout << "IO destructor" << std::endl;
}

void IO::loop()
{
    std::cout << "Loop start" << std::endl;

    const std::vector<int> offsets = {
         GPIO_PORT_1_LINE,
         GPIO_PORT_2_LINE,
         GPIO_PORT_3_LINE,
         GPIO_PORT_4_LINE };

    try
    {
        // Open chip
        std::filesystem::path chip_path(GPIO_CHIP_NAME);

        std::cout << "STEP 1" << std::endl;

        // Get the requested lines
        gpiod::line::offsets line_offsets;

        for (int offset : offsets)
            line_offsets.push_back(offset);

        std::cout << "STEP 2" << std::endl;

        auto chip = gpiod::chip(chip_path);

        std::cout << "STEP 3" << std::endl;

        // Prepare que line request
        auto request_builder = chip.prepare_request();

        std::cout << "STEP 4" << std::endl;

        // Set the consumer
        request_builder.set_consumer("io_test");

        std::cout << "STEP 5" << std::endl;

        // Create the line settings
        gpiod::line_settings line_settings;
        line_settings.set_direction(gpiod::line::direction::INPUT);
        line_settings.set_edge_detection(gpiod::line::edge::BOTH);

        std::cout << "STEP 6" << std::endl;

        // Add the line settings
        request_builder.add_line_settings(line_offsets, line_settings);

        std::cout << "STEP 7" << std::endl;

        // Request the line
        auto request = request_builder.do_request();

        std::cout << "STEP0 8" << std::endl;

        gpiod::edge_event_buffer buffer;

        while (true)
        {
            std::cout << "BLOCK WAIT" << std::endl;

            /* Blocks until at leat one event available */
            request.read_edge_events(buffer);
            std::cout << "LINE READ" << std::endl;

            for (const auto &event : buffer)
            {
                std::cout << "IO EVENT" << std::endl;

                std::cout << "offset: " << event.line_offset()
                          << "  event #" << event.global_seqno()
                          << "  line event #" << event.line_seqno()
                          << "  timestamp " << event.timestamp_ns().ns()
                          << ::std::endl;

                auto type = event.type();
                auto ns = std::chrono::nanoseconds(event.timestamp_ns().ns());
            }
        }
    }
    catch (const std::exception &e)
    {
        std::cerr << "Error: " << e.what() << std::endl;
    }
}

运行程序时出现以下错误:

IO Constructor
Loop start
STEP 1
STEP 2
STEP 3
STEP 4
STEP 5
STEP 6
STEP 7
Error: error requesting GPIO lines: Device or resource busy

已使用gpiomon工具正常访问这些线路并获取数据变化,确认无其他程序占用线路,重启设备后问题仍存在。需排查问题原因、函数调用顺序是否正确、是否遗漏关键调用。


解决方法

1. 排查GPIO线路的内核占用情况

"Device or resource busy"最常见的原因是目标GPIO线路被内核驱动占用(而非用户程序)。即使gpiomon能运行,也可能是它使用了不同的配置绕过了内核占用,或者某一条线路单独被占用导致批量请求失败。

运行以下命令查看线路状态:

gpioinfo /dev/gpiochip0

查看offset 0、1、5、6对应的行,如果显示used,说明该线路被内核模块(如LED、按键驱动)绑定,需要先解除绑定:

  • 修改设备树,禁用对应GPIO的内核驱动配置;
  • 卸载占用线路的内核模块(如rmmod <module-name>)。

2. 修复代码中的潜在问题

你的代码调用顺序大体正确,但存在几个细节问题:

  • 重复包含头文件:同时包含<gpiod.hpp>和"gpiod.hpp"可能导致重复定义冲突,建议只保留其中一个;
  • 边缘检测兼容性:部分GPIO硬件不支持边缘检测,或需要先配置上拉/下拉电阻。可以尝试先移除set_edge_detection调用,测试是否能成功请求线路,再逐步添加边缘检测逻辑;
  • 批量请求排查:尝试单独请求某一条线路(比如只保留offset 0),如果能成功,说明是某条线路的问题,逐一排查找到故障线路。

3. 验证libgpiod版本兼容性

你参考的是v2.1.x的示例代码,需确保系统安装的libgpiod版本为v2.x系列(v1.x和v2.x的API差异极大)。运行以下命令确认版本:

gpiodetect --version

如果版本不匹配,需升级或降级libgpiod到对应版本。

4. 权限验证

虽然权限问题通常提示Permission denied,但仍可尝试用sudo运行程序,排除权限导致的隐性问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:14:52