sysfs GPIO와 libgpiod, 언제 무엇을?
리눅스 유저 스페이스에서 GPIO를 다룰 때 선택지는 크게 둘입니다. 구형 sysfs(/sys/class/gpio)와 GPIO character device(/dev/gpiochipX)를 감싼 libgpiod입니다.
커널 문서는 sysfs userspace API를 obsolete로 두고, 대체 경로를 GPIO Character Device Userspace API로 명시합니다. libgpiod 프로젝트 문서도 동일하게 legacy sysfs를 대체하는 쪽이 character device + libgpiod라고 말합니다.
이 글의 축은 언제 무엇을 고를지뿐입니다. 라인 요청·C API 절차는 libgpiod 본편, rising/falling 옵션·debounce는 gpiomon 엣지편에 맡깁니다. 보드별 핀맵 후기·창작 실측은 없습니다.
근거: Sysfs Interface, Obsolete GPIO interfaces, GPIO character device, libgpiod.
sysfs는 언제?
한 줄 답: 신규 개발의 기본값이 아닙니다. 이미 sysfs에 묶인 레거시 스크립트·BSP 문서 경로를 유지·이전하는 동안, 또는 대상 커널/이미지에 character device·libgpiod가 아직 없는 경우에만 검토합니다. 커널은 마이그레이션 기간 유지·신규 기능은 새 API에만 추가한다고 경고합니다.
sysfs 경로의 골격(/sys/class/gpio/):
| 항목 | 역할 |
|---|---|
export / unexport | 전역 GPIO 번호를 userspace로 내보내거나 회수 |
gpioN/direction, gpioN/value | 방향·값 읽기/쓰기 |
gpioN/edge, gpioN/active_low | (지원 시) poll용 엣지·활성 극성 |
gpiochipN/base, label, ngpio | 컨트롤러 구간 정보(읽기 전용) |
선택 시 현실적 조건:
- 레거시 계약 — 기존 이미지·공장 스크립트가
echo N > export패턴에 고정돼 있고, 당장 교체 비용이 더 큼. - 문서화된 전역 번호 — BSP가 “GPIO #23 = …”처럼 전역 번호로만 적혀 있고, 당분간 chip+offset 매핑을 바꾸지 않음. (커널 문서도 번호가 보드/카드 조합에 따라 흔들릴 수 있다고 경고합니다.)
- 도구 부재 — 타깃에
/dev/gpiochip*또는 libgpiod 패키지가 없고, 셸·파일 I/O만으로 최소 조작이 필요함. - 커널이 이미 export한 디버그 노드 — 드라이버가
gpiod_export()로 노출한 노드를 문서화된 BSP 인터페이스로 쓰는 경우(여전히 “새 기능 개발” 축은 아님).
하지 말아야 할 축:
- 신규 앱·서비스의 기본 GPIO 경로로 sysfs를 고르기 — 커널 경고와 반대입니다.
- 이미 전용 커널 드라이버가 있는 하드웨어를 userspace에서 bitbang — sysfs·chardev 공통 금지(커널 GPIO userspace 문서의 “Do NOT abuse…”).
- 이 글로 gpiomon/엣지 튜닝을 대체하기 — 엣지 대기·옵션은 별도 편입니다.
libgpiod 이점은?
한 줄 답: libgpiod는 obsolete sysfs 대신 GPIO character device(ioctl) 를 C 라이브러리·바인딩·CLI로 감쌉니다. FD를 닫으면 할당 자원이 정리되고, 신뢰할 수 있는 이벤트, 여러 라인 동시 읽기/쓰기, open-drain/open-source 등 sysfs에 없거나 약한 구성이 character device 쪽에 있습니다.
선택 축에서 보는 이점(howto가 아니라 왜 고르나):
| 축 | sysfs | character device + libgpiod |
|---|---|---|
| 식별 | 전역 GPIO 번호 | Chip(/dev/gpiochipX) + line offset(또는 라인 이름) |
| 수명 | export 노드·파일 상태 | Line Request; 디바이스 FD 종료 시 자원 해제(libgpiod/커널 설명) |
| 이벤트 | value에 대한 poll 등 | 라인 요청 기반 edge event(도구·API는 본편/gpiomon편) |
| 다중 라인 | 파일별로 반복 | 한 요청에서 여러 값 get/set |
| 전기 구성 | 제한적 | open-drain/open-source, bias 등(커널 uAPI·라이브러리) |
| 신규 기능 | 추가되지 않음(obsolete) | 새 기능은 이쪽에만 |
언제 libgpiod(또는 동일 chardev uAPI)를 기본으로 고를지:
- 신규 userspace — 커널·libgpiod 문서의 권장 경로.
- 칩·오프셋(또는 라인 이름)으로 안정적으로 지칭 — 전역 번호 흔들림을 피함.
- 요청 수명·해제를 프로세스 FD에 묶고 싶을 때 — 종료 시 자동 정리 모델.
- 다중 라인·엣지·드라이브/바이어스 구성이 필요할 때 — sysfs로 우회하지 않음.
이 글은 gpiodetect/gpioget/gpioset/gpiomon의 옵션 해설을 하지 않습니다. 도구 사용법·엣지 옵션은 libgpiod 본편과 gpiomon 엣지편을 보십시오.
권한은?
한 줄 답: 인터페이스가 다르면 권한 면도 다릅니다. sysfs는 /sys/class/gpio 아래 export·gpioN 속성 파일의 소유/모드가 막으면 실패하고, libgpiod는 보통 /dev/gpiochip* 문자 디바이스를 open할 수 있어야 합니다. 배포판 기본이 root-only이면 udev GROUP/MODE + 그룹 멤버십으로 맞춥니다.
비교:
| sysfs | libgpiod / chardev | |
|---|---|---|
| 접근 대상 | export/unexport, gpioN/* | /dev/gpiochipX (이후 요청 FD) |
| 흔한 실패 | Permission denied on export/value | Permission denied opening gpiochip |
| 비root 관행 | gpio 그룹 등에 sysfs 노드 chgrp/chmod(보드·이미지별 udev) | SUBSYSTEM=="gpio", KERNEL=="gpiochip*", GROUP="gpio", MODE="0660" 류 규칙 + 사용자를 gpio에 추가 |
예시(배포판·이미지에 맞게 조정; 그룹 이름은 환경에 따름):
# /etc/udev/rules.d/90-gpio.rules (예시)
SUBSYSTEM=="gpio", KERNEL=="gpiochip[0-9]*", GROUP="gpio", MODE="0660"
sudo groupadd -f gpio
sudo usermod -aG gpio "$USER"
# 재로그인 후
ls -l /dev/gpiochip*
# 기대 예: crw-rw---- root gpio
실무 체크:
- 어느 경로를 쓰는지 먼저 고정 — sysfs 레거시면 sysfs 노드 권한, 신규면 gpiochip 노드 권한.
- sudo로만 검증하지 않기 — 서비스 사용자·그룹이 실제 런타임과 같아야 합니다.
- udev reload/trigger 후
ls -l— 규칙만 넣고 그룹이 안 바뀐 채 Permission denied가 남는 경우가 많습니다. - sysfs와 chardev를 동시에 “임시로” 쓰지 않기 — 같은 라인을 두 인터페이스로 건드리면 소유·요청 충돌이 납니다. 마이그레이션은 한 경로로 수렴이 목표입니다.
FAQ
신규 프로젝트에 sysfs를 써도 되나요?
커널은 신규 개발에 character device API를 쓰고, 기존 것도 가능하면 이전하라고 합니다. sysfs는 마이그레이션·레거시 유지용으로 보는 것이 맞습니다.
libgpiod 없이 /dev/gpiochip만 쓰면?
가능합니다. 커널 uAPI(ioctl)를 직접 다룰 수 있습니다. libgpiod는 그 ioctl을 라이브러리·CLI로 감싼 것이며, 선택 축의 “새 경로”는 character device입니다.
gpiomon 엣지 글·libgpiod 본편과 차이는?
본편은 Chip/Line Request·get/set 흐름, gpiomon편은 엣지 옵션·폴링 대비입니다. 이 글은 sysfs vs libgpiod(chardev) 선택·이점·권한만 다룹니다.
chardev v1은?
커널 obsolete 목록에 Character Device Userspace API (v1)도 포함됩니다. 현재 문서상 최신 userspace 경로는 v2(커널 5.10+). libgpiod 메이저 버전에 따라 요구 uAPI가 다르므로 패키지·커널을 맞추십시오.
출처 (Sources)
- GPIO Sysfs Interface — obsolete 경고, export/value/edge, gpiochip sysfs
- Obsolete GPIO Userspace APIs — sysfs·chardev v1
- GPIO Character Device Userspace API — Chip, Line Request,
/dev/gpiochipX - libgpiod documentation — sysfs 대체, FD 해제, 이벤트·다중 값·open-drain/source