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컨트롤러 구간 정보(읽기 전용)

선택 시 현실적 조건:

  1. 레거시 계약 — 기존 이미지·공장 스크립트가 echo N > export 패턴에 고정돼 있고, 당장 교체 비용이 더 큼.
  2. 문서화된 전역 번호 — BSP가 “GPIO #23 = …”처럼 전역 번호로만 적혀 있고, 당분간 chip+offset 매핑을 바꾸지 않음. (커널 문서도 번호가 보드/카드 조합에 따라 흔들릴 수 있다고 경고합니다.)
  3. 도구 부재 — 타깃에 /dev/gpiochip* 또는 libgpiod 패키지가 없고, 셸·파일 I/O만으로 최소 조작이 필요함.
  4. 커널이 이미 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가 아니라 왜 고르나):

축sysfscharacter 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)를 기본으로 고를지:

  1. 신규 userspace — 커널·libgpiod 문서의 권장 경로.
  2. 칩·오프셋(또는 라인 이름)으로 안정적으로 지칭 — 전역 번호 흔들림을 피함.
  3. 요청 수명·해제를 프로세스 FD에 묶고 싶을 때 — 종료 시 자동 정리 모델.
  4. 다중 라인·엣지·드라이브/바이어스 구성이 필요할 때 — sysfs로 우회하지 않음.

이 글은 gpiodetect/gpioget/gpioset/gpiomon의 옵션 해설을 하지 않습니다. 도구 사용법·엣지 옵션은 libgpiod 본편과 gpiomon 엣지편을 보십시오.

권한은?

한 줄 답: 인터페이스가 다르면 권한 면도 다릅니다. sysfs는 /sys/class/gpio 아래 export·gpioN 속성 파일의 소유/모드가 막으면 실패하고, libgpiod는 보통 /dev/gpiochip* 문자 디바이스를 open할 수 있어야 합니다. 배포판 기본이 root-only이면 udev GROUP/MODE + 그룹 멤버십으로 맞춥니다.

비교:

sysfslibgpiod / chardev
접근 대상export/unexport, gpioN/*/dev/gpiochipX (이후 요청 FD)
흔한 실패Permission denied on export/valuePermission 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

실무 체크:

  1. 어느 경로를 쓰는지 먼저 고정 — sysfs 레거시면 sysfs 노드 권한, 신규면 gpiochip 노드 권한.
  2. sudo로만 검증하지 않기 — 서비스 사용자·그룹이 실제 런타임과 같아야 합니다.
  3. udev reload/trigger 후 ls -l — 규칙만 넣고 그룹이 안 바뀐 채 Permission denied가 남는 경우가 많습니다.
  4. 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)