libgpiod

libgpiod는 리눅스 유저 스페이스(Linux userspace)가 GPIO character device를 통해 GPIO 라인과 상호작용하게 하는 C 라이브러리, 언어 바인딩 및 명령줄 도구입니다.

이 글은 libgpiod 공식 문서와 Linux 커널 GPIO 문서를 2026-09-01 기준으로 정리한 일반 설명이며, 커널 및 라이브러리 버전에 따라 세부 동작은 달라질 수 있습니다.

libgpiod는 무엇인가?

한 줄 답: 이 프로젝트는 ioctl 기반 GPIO character device 접근을 C 라이브러리, 언어 바인딩, 명령줄 도구로 감싸며, 유저 스페이스의 기본 단위로 Chip과 Line Request를 사용합니다.

기존의 GPIO sysfs 인터페이스는 커널에서 deprecated된 이전 경로이며, GPIO character device는 Linux 커널 4.8에 도입된 더 유연하고 효율적인 경로입니다. 디바이스 파일 디스크립터를 닫으면 이 인터페이스가 할당한 자원이 안전하게 해제되며, 신뢰할 수 있는 이벤트 polling, 여러 값의 동시 읽기 및 설정, open-source와 open-drain GPIO 같은 고급 기능도 제공합니다.

커널 userspace API에서 Chip은 /dev/gpiochipX로 노출되는 GPIO 컨트롤러 객체입니다. 각 Chip은 chip.lines개의 라인을 가지며, 라인은 0부터 chip.lines - 1까지의 offset으로 식별합니다. 라인을 Chip에서 요청하면 Line Request가 만들어지고, 유저 스페이스는 그 요청을 통해 라인 값에 접근하거나 edge event를 감시합니다.

공식 문서에는 고수준 언어 바인딩, D-Bus 인터페이스, 테스트 항목도 포함되지만, 이 글의 주 경로는 C API명령줄 도구입니다. 이 프로젝트는 일반 명령줄 도구만으로 다루기 번거로운 ioctl 기반 커널-유저 스페이스 상호작용을 편의 함수와 불투명 자료구조로 깔끔하게 감쌉니다.

디바이스 트리는 핀을 설명하고, 이 라이브러리는 유저 스페이스에서 라인을 요청합니다. 관련 배경은 디바이스 트리에서 확인할 수 있습니다.

임베디드 시스템이란은 보드를 전용 컴퓨터로 보는 맥락만 연결하며, 이 글에서는 그 정의를 다시 다루지 않습니다.

sysfs GPIO와 무엇이 다른가?

한 줄 답: 신규 유저 스페이스 개발에는 전역 번호를 사용하는 obsolete sysfs보다 Chip과 offset을 사용하는 GPIO character device를 선택해야 합니다.

이전 sysfs 경로는 /sys/class/gpio/ 아래에서 exportunexport를 사용하고, 개별 라인을 /sys/class/gpio/gpioN/과 전역 GPIO 번호로 표현했습니다. 반면 character device 경로는 /dev/gpiochipX라는 Chip과 그 안의 라인 offset을 함께 사용합니다.

커널 문서는 sysfs userspace APIGPIO Character Device Userspace API로 대체된 obsolete 인터페이스로 설명합니다. 이전 경로는 마이그레이션 기간 동안 유지되지만 새 기능은 character device API에만 추가되며, 신규 개발은 새 API를 사용하고 기존 개발도 가능한 한 마이그레이션해야 합니다.

character device는 이벤트 polling, 여러 라인의 값을 한 번에 읽고 설정하는 기능, open-source·open-drain 같은 전기적 구성, 디바이스 파일 디스크립터를 닫을 때의 자원 정리를 제공합니다. 따라서 sysfs의 전역 번호와 파일별 상태 항목을 새 userspace 모델의 기준으로 삼아서는 안 됩니다.

Character Device v1도 obsolete userspace API에 포함되므로, 이 글에서 설명하는 현재 경로는 kernel userspace API v2입니다. v2는 Linux 커널 5.10에 처음 추가되었으며, 커널 driver API의 gpio_chip 내부 구현은 여기서 다루지 않습니다.

라인을 요청하고 읽고 쓰는 법은?

한 줄 답: gpiodetectgpioinfo로 대상을 확인한 뒤 라인을 요청하고, gpioget 또는 gpioset으로 읽거나 설정하며, 요청 수명 안에서만 제어 권한을 유지합니다.

gpiodetect는 시스템의 GPIO Chip, 이름, label, 라인 수를 나열합니다. gpioinfo는 Chip, offset, 라인 이름, direction을 보여 주고, 사용 중인 라인이라면 consumer와 active state, bias, drive, edge detection, debounce period 같은 구성 속성도 보여 줍니다. gpioget은 지정한 라인의 값을 읽고, gpioset은 지정한 라인의 값을 설정합니다.

라인은 이름으로 지정할 수 있고, Chip을 -c 또는 --chip으로 제한한 경우에는 offset으로도 지정할 수 있습니다. gpioget--numeric은 값을 비활성 0 또는 활성 1로 표시합니다. gpiomongpionotify도 각각 edge event와 정보 변경을 기다리는 도구로 존재하지만, 기본 경로는 detect·info·get·set입니다.

gpioset은 프로세스가 종료되거나 중단될 때까지 요청한 라인을 잡고 값을 유지합니다. 프로세스가 종료되면 요청한 라인은 자동으로 해제되고 커널이나 다른 프로세스가 상태를 바꿀 수 있으므로, 종료 뒤에도 값이 유지된다고 가정할 수 없습니다. 요청한 값을 보장하기 위해 기본적으로 종료하지 않는 동작을 사용합니다.

다음은 공식 문서에 제시된 명령 예입니다. 문서의 예시에는 Raspberry Pi 4B가 언급되지만, 이 글의 보드 실측이나 보편적인 핀맵을 뜻하지 않습니다.

$ gpioget -c 0 15
$ gpioset GPIO23=1

C API에서는 gpiod_chip_open(path)으로 Chip을 열고 gpiod_chip_close(chip)으로 닫습니다. gpiod_chip_request_lines(chip, req_cfg, line_cfg)은 라인 묶음의 배타적 사용을 요청하며, req_cfg는 기본 설정을 위해 NULL일 수 있지만 line_cfg는 필요합니다. 반환된 Line Request는 gpiod_line_request_release(request)로 해제해야 합니다.

요청을 얻은 뒤 gpiod_line_request_get_value(request, offset)은 단일 라인 값을 성공 시 1 또는 0으로 반환하고 오류 시 -1을 반환합니다. gpiod_line_request_set_value(request, offset, value)는 성공 시 0, 실패 시 -1을 반환하며, 모든 요청 라인의 값을 다루는 gpiod_line_request_get_valuesgpiod_line_request_set_values도 제공됩니다.

커널 수준에서는 GPIO_V2_GET_LINE_IOCTL이 Line Request를 만들고, 그 요청 파일 디스크립터에서 라인 값을 읽고 설정하는 방식으로 대응합니다. 적절한 커널 드라이버가 있는 하드웨어는 userspace API로 직접 제어하지 않아야 합니다.

칩과 라인은 어떻게 고르나?

한 줄 답: Chip은 번호, 이름, 장치 경로로 식별하고, 선택한 Chip 안의 라인은 이름을 우선 확인한 뒤 필요하면 해당 Chip의 offset으로 지정합니다.

GPIO Chip은 번호, 이름, 경로로 식별할 수 있습니다. 예를 들어 0, gpiochip0, /dev/gpiochip0은 같은 Chip을 가리킬 수 있습니다. gpiodetect는 Chip의 label과 라인 수를 출력하고, 인자를 지정하지 않으면 시스템의 모든 Chip을 나열합니다.

gpioinfo는 라인의 Chip, offset, name, direction을 확인하는 데 사용하며, 사용 중이면 consumer와 active state, bias, drive, edge detection, debounce period 같은 속성도 표시합니다. 라인 이름을 지정하는 방식이 읽기 쉽고, 특정 Chip을 --chip으로 제한한 명령에서는 offset을 사용할 수 있습니다.

라인 offset의 유효 범위는 0부터 chip.lines - 1까지입니다. C helper인 gpiod_chip_get_line_offset_from_name(chip, name)은 라인 이름을 offset으로 매핑하며, 이름을 찾지 못하면 -1을 반환하고 errnoENOENT로 설정합니다.

다음 출력은 공식 문서의 Raspberry Pi 4B 작성 예시입니다. pinctrl-bcm2711이나 raspberrypi-exp-gpio를 모든 보드에서 쓰는 Chip 이름으로 해석해서는 안 됩니다.

$ gpiodetect
gpiochip0 [pinctrl-bcm2711] (58 lines)
gpiochip1 [raspberrypi-exp-gpio] (8 lines)

FAQ

한 줄 답: 권장 userspace 인터페이스, sysfs의 상태, Chip 선택 방식, gpioset 종료 뒤의 수명을 구분하면 기본 사용 경로를 판단할 수 있습니다.

리눅스 유저 스페이스에서 GPIO 라인을 다루려면 무엇을 사용합니까?

GPIO character device와 이 라이브러리의 C API 또는 명령줄 도구를 사용합니다. Chip을 확인하고 라인을 요청한 뒤 값을 읽거나 설정하는 흐름입니다.

sysfs /sys/class/gpio는 아직 사용합니까?

마이그레이션 기간에는 유지되지만 obsolete 인터페이스입니다. 신규 개발은 GPIO character device userspace API를 사용해야 합니다.

Chip은 어떻게 고릅니까?

번호, 이름, 경로 중 하나로 고를 수 있으며, 0, gpiochip0, /dev/gpiochip0처럼 같은 Chip을 서로 다른 표기로 지정할 수 있습니다.

gpioset을 종료하면 라인 값이 유지됩니까?

보장되지 않습니다. 프로세스가 종료되면 요청한 라인이 자동으로 해제되어 커널이나 다른 프로세스가 상태를 변경할 수 있습니다.

출처

한 줄 답: 본문은 2026-09-01 기준으로 확인한 프로젝트 공식 문서와 Linux 커널 GPIO 문서만 근거로 사용합니다.