Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
Tags
- /dev
- qt widget
- systemd
- SQLite
- 노션
- 임베디드 리눅스
- wiringpi
- 캐릭터 디바이스
- cdev
- pthreads
- 바이브 코딩
- raspberry pi 4
- 가계부 개발
- 디바이스 트리 작성법
- 개발자 취준
- 취준
- IOT
- 라즈베리파이
- udev
- 라즈베리파이 카메라
- .so 라이브러리
- yocto
- 디바이스 트리
- ioctl
- 금융권 취준
- rtsp
- 리눅스 커널 드라이버
- 커널 모듈
- 멀티클라이언트
- 데몬 프로세스
Archives
- Today
- Total
이로또
임베디드 리눅스 드라이버의 이해 4편: 인터럽트 처리의 원리 본문
이 글에서는 리눅스 커널에서의 인터럽트가 무엇인지, 어떤 흐름으로 처리되는지, 그리고 우리가 만든 디바이스 드라이버에서 인터럽트를 어떻게 등록하고 사용하는지를 예제를 통해 정리합니다.
인터럽트는 외부 버튼이나 센서처럼 갑작스럽게 발생하는 이벤트에 반응하기 위한 핵심 개념입니다.
목차
- 인터럽트란?
- 인터럽트 처리 흐름 쉽게 이해하기
- 커널 내부 인터럽트 처리 과정
- 디바이스 드라이버에서 인터럽트 등록하기
- 실습 예제: 버튼 입력 처리
- 인터럽트 등록 확인하기 - /proc/interrupts
- request_irq 함수 자세히 보기
- 정리 요약
1. 인터럽트란?
인터럽트란? "갑자기 CPU한테 중요한 일이 생겼어요! 라고 알리는 것"
예를 들어:
- 사람이 키보드를 누름 → 키보드 장치가 CPU에게 알림
- 타이머가 종료됨 → CPU에게 알림
이렇게 장치에서 "지금 나를 처리해줘!"라고 CPU에 요청하는 것이 바로 인터럽트입니다.
2. 인터럽트 처리 흐름 쉽게 이해하기
- CPU는 프로그램을 실행 중
- 외부 장치에서 인터럽트 발생 (예: 버튼 누름)
- CPU는 잠시 작업을 멈추고, 인터럽트 처리 함수로 이동
- 인터럽트 핸들러(처리 함수) 실행
- 처리 끝나면 원래 하던 일로 복귀
즉, 인터럽트는 CPU가 외부의 신호에 빠르게 반응하도록 도와주는 메커니즘입니다.
3. 커널 내부 인터럽트 처리 과정
리눅스 커널 안에서는 아래와 같은 흐름으로 인터럽트를 처리합니다:
- asm_do_irq() → CPU 아키텍처 레벨에서 인터럽트 진입
- do_IRQ(n) → 인터럽트 번호 n을 받아서 처리
- irq_desc[n] → 해당 번호에 등록된 처리 함수 확인
- 등록된 핸들러 함수 실행 → 우리가 작성한 ISR (Interrupt Service Routine)
4. 디바이스 드라이버에서 인터럽트 등록하기
커널은 "어떤 인터럽트 번호에 어떤 함수를 실행할지" 미리 등록해두어야 합니다.
이를 위해 사용하는 함수가 request_irq()입니다.
예시:
request_irq(PIN_KEY1_irq, isr_func, IRQF_TRIGGER_RISING, "my_device", NULL);
- PIN_KEY1_irq: IRQ 번호 (어떤 핀에 연결된 인터럽트인지)
- isr_func: 실제 처리할 함수
- IRQF_TRIGGER_RISING: 상승 에지(버튼이 눌렸을 때) 트리거
- "my_device": 장치 이름
- NULL: 장치 식별자 (필요 시 구조체 주소 등)
인터럽트가 더 이상 필요 없을 때는 free_irq()로 해제합니다.
5. 실습 예제: 버튼 입력 처리
1. GPIO 설정
gpio_request(PIN_KEY1, "PIN_KEY1");
gpio_direction_input(PIN_KEY1);
PIN_KEY1_irq = gpio_to_irq(PIN_KEY1);
- 버튼이 연결된 GPIO를 입력 모드로 설정하고, IRQ 번호를 얻어옵니다.
2. 인터럽트 핸들러 작성
static irqreturn_t isr_func(int irq, void *dev_id, struct pt_regs *regs) {
printk("(isr) Button pressed!\n");
return IRQ_HANDLED;
}
3. 인터럽트 등록
request_irq(PIN_KEY1_irq, isr_func, IRQF_TRIGGER_RISING, "my_device", NULL);
4. 해제 시
free_irq(PIN_KEY1_irq, NULL);
6. 인터럽트 등록 확인 - /proc/interrupts
cat /proc/interrupts
- IRQ 번호별로 인터럽트가 얼마나 발생했는지 확인 가능
- 내가 등록한 "my_device" 이름이 있는지 확인 가능
7. request_irq() 함수 자세히 보기
int request_irq(unsigned int irq,
irq_handler_t handler,
unsigned long flags,
const char *name,
void *dev);
인자 | 설명 |
irq | IRQ 번호 (어느 핀에 연결된 인터럽트인지) |
handler | 처리할 함수 (ISR) |
flags | 언제 인터럽트를 감지할지: 상승 에지, 하강 에지 등 |
name | 장치 이름 (/proc/interrupts에 나옴) |
dev | 장치 구분자 (여러 장치가 같은 IRQ 쓸 때 사용) |
8. 정리 요약
개념 | 설명 |
인터럽트 | 외부 이벤트에 CPU가 즉시 반응하는 시스템 |
ISR | 인터럽트가 발생했을 때 실행되는 함수 |
request_irq() | 인터럽트와 ISR을 등록하는 함수 |
free_irq() | 등록 해제하는 함수 |
/proc/interrupts | 등록된 인터럽트와 발생 횟수 확인 |
'임베디드' 카테고리의 다른 글
임베디드 리눅스 드라이버의 이해 6편: 커널 영역에서 쓰레드 만들기 (0) | 2025.06.04 |
---|---|
임베디드 리눅스 드라이버의 이해 5편: 커널과 하드웨어의 연결 (0) | 2025.06.04 |
임베디드 리눅스 드라이버의 이해 3편: 커널에서의 메모리 할당 (0) | 2025.06.04 |
임베디드 리눅스 드라이버의 이해 2편: 캐릭터 디바이스와 장치 파일, ioctl (0) | 2025.05.27 |
임베디드 리눅스 커널 구조와 드라이버의 이해 1편 (0) | 2025.05.26 |