提问人:First dev 提问时间:4/30/2023 更新时间:5/1/2023 访问量:369
树莓派 GPIO sysfs,fopen:权限被拒绝
Raspberry pi GPIO sysfs, fopen: Permission denied
问:
我正在尝试通过使用 C 语言的 sysfs 使用树莓派 GPIO,但是在尝试更改 GPIO 线路方向时,我不断得到。
尝试打开文件时出现此问题。fopen: Permission denied
"/sys/class/gpio/gpio18/direction"
笔记:
- 如果我第二次运行该程序,它可以正常工作。
- 如果我手动导出GPIO行,然后执行它就可以正常工作了。
- 如果我以 root 身份运行该程序,它可以正常工作。
- 我当前的用户是 gpio 组的一部分,应该具有所有权限。
通常,我需要将要使用的引脚放入 .
然后我需要通过写入或设置它的方向(输出/输入)。"/sys/class/gpio/export"
1
0
"/sys/class/gpio/gpio18/direction"
为了以编程方式实现这一点,我使用以下代码
#include "io.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char const* argv[]) {
// export line
FILE* p_gpio_line;
if ((p_gpio_line = fopen("/sys/class/gpio/export", "w")) == NULL) {
printf("Cannot open export file.\n");
perror("fopen");
exit(1);
}
rewind(p_gpio_line);
fwrite("18", sizeof(char), 2, p_gpio_line);
fclose(p_gpio_line);
// set direction
FILE* p_gpio_direction;
if ((p_gpio_direction = fopen("/sys/class/gpio/gpio18/direction", "r+")) == NULL) {
printf("Cannot open direction file.\n");
perror("fopen");
exit(1);
}
return 0;
}
第一次执行时,我得到
Cannot open direction file.
fopen: Permission denied
第二次工作正常,因为在执行程序之前导出了GPIO线(从第一次执行开始)
如果我从终端手动导出GPIO线,它也可以正常工作
答:
1赞
dimich
4/30/2023
#1
我的评论仍然有效,但实际上在您的示例中返回 EACCES(“权限被拒绝”)。perror()
fopen()
组和权限特定于 Raspberry Pi 发行版。它们由 udev 规则设置:gpio
/sys/class/gpio
/etc/udev/rules.d/99-com.rules
SUBSYSTEM=="gpio", ACTION=="add", PROGRAM="/bin/sh -c 'chgrp -R gpio /sys%p && chmod -R g=u /sys%p'"
Udev 规则在文件出现后异步应用。您正在尝试打开文件,但尚未设置权限。direction
我建议使用带有 libgpiod 的字符设备 GPIO 接口,而不是已弃用的 sysfs 接口。
如果您仍想使用 sysfs 接口,简单的解决方案是重试直到成功(或失败并出现 EACCES 以外的错误或超时)。例如:fopen()
// Open timeout, ms
#define DIR_OPEN_TIMEOUT_MS 3000
// Delay between retries, ms
#define DIR_POLL_DELAY_MS 100
...
// set direction
FILE* p_gpio_direction;
unsigned int retries_left = DIR_OPEN_TIMEOUT_MS / DIR_POLL_DELAY_MS;
while (1)
{
p_gpio_direction = fopen("/sys/class/gpio/gpio18/direction", "r+");
if (p_gpio_direction)
break;
if ((errno != EACCES) || (retries_left-- == 0)) {
printf("Cannot open direction file: %m\n");
exit(1);
}
const struct timespec rqt = {
.tv_sec = DIR_POLL_DELAY_MS / 1000,
.tv_nsec = 1000000L * (DIR_POLL_DELAY_MS % 1000)
};
if (nanosleep(&rqt, NULL) == -1)
perror("nanosleep()");
}
...
评论
0赞
First dev
5/1/2023
这解释了它,谢谢,一个问题,如果我仍然想使用 sysfs,我该如何等待规则应用后再访问文件?direction
0赞
0andriy
5/2/2023
这不是解决问题的好方向。我们需要启用 GPIO,不得使用 sysfs。libgpiod
评论
perror()
printf()
errno
perror()
libgpiod