디버깅이란 무엇인가
디버깅에 대한 일반적인 관점
- 디버깅은 'debug'와 '-ing'의 합성어
- '디버깅 하고 있다' == '버그를 수정하고 있다'
- 버그와 관련된 기능의 개발자가 버그를 잡기 위해 디버깅을 함
리눅스 시스템 환경에서 디버깅이란
오픈 소스 프로젝트인 리눅스 커널의 특징
- 리눅스 커널은 자신이 작성한 코드보다 다른 개발자가 작성한 코드로 구성됨(칩셋 업체 BSP, 외부 업체 코드)
- 자신이 작성한 코드보다 다른 개발자의 코드를 훨씬 더 많이 분석해야 함
디버깅이 중요한 이유
실전 프로젝트에서 디버깅이 중요한 이유
- 프로젝트에서 신뢰성 테스트를 거치며 이 과정에서 버그가 리포트됨
- 디버깅을 잘해야 자신의 구현한 코드의 논리적 오류를 찾아 해결할 수 있음
- 디버깅을 잘하면 다른 모듈의 코드를 빨리 읽고 분석할 수 있어 코드 학습에 유리
현업에서 Device Driver 개발
디버깅이란 무엇인가
오픈 소스 프로젝트인 리눅스 커널의 특징
- 오픈 소스 특성 상 리눅스 커널은 여러 개발자가 작성한 코드로 구성됨
- 다른 개발자의 코드를 훨씬 더 많이 분석해야 함
- 리눅스 Device Driver는 리눅스 커널이 제공하고 있는 함수를 호출함
디버깅 능력 - Narrow Down
문제를 좁혀서 생각하는 습관 : Narrow Down
- 터치가 잘 동작하지 않는다
- 터치 패널에서 인터럽트가 제대로 올라올까?
- 터치 패널에 이물질이 남아 있지 않을까?
- 인터럽트 핸들러를 통해 좌표가 제대로 전달될까?
- 멀티 터치 이벤트가 제대로 전달될까?
- 불량 터치 패널일까?
디버깅 능력 - Narrow Down 능력과 개발 역량
문제를 좁혀서 생각하는 습관 : Narrow Down
- Narrow Down 능력은 시스템의 이해도에 비례
- Arm 아키텍처, 리눅스 커널
- Case Study 참고
인터럽트 처리 : Big Picture
Touch 인터럽트

리눅스 시스템 개발 도중 만나는 문제 유형
Crash
- 부팅 도중 Kernel Crash 발생
- 스트레스 테스트 도중 Crash 발생(Exception)
- 화면이 꺼진 다음에 키면 무감 현상 확인(Freeze)
- 와치독 리셋 발생
오동작1
- 인터럽트에 대한 적절한 처리가 되지 않음
- 인터럽트를 설정한 후 인터럽트가 해당 Periperal에서 유발되지 않음
- 인터럽트 핸드러를 설정했는데 인터럽트 핸들러가 호출되지 않음
오동작2
- 파일 복사가 안 됨
- 카메라를 촬영 후 파일이 저장되지 않음
- 배터리가 제대로 충전되지 않음
- 소리가 재생되지 않음
성능 이슈
- 시스템 응답 속도가 매우 느려짐 -> Memory Leak
- 애플리케이션 실행 속도가 느림
- 소리가 끊김
- 화면이 끊김
ftrace로 확인해보자
(메모리 : 리눅스 커널에서 Page 단위로 관리)
디버깅 과정
리눅스 시스템 개발을 할 때 디버깅의 과정
- 실전 개발에서 테스트 도중 문제가 생기면 테스트 개발자나 부서에서 오류 정보가 담긴 커널 로그나 메모리 덤프(Core Dump)를 개발자에게 전달
- 개발자는 오류가 발생했을 때 커널 로그나 메모리 덤프에서 코드나 자료구조의 어떤 부분이 잘못됐는지 식별해야 함
- 커널 로그에서 오류 정보를 바로 식별할 수 있으면 좋겠지만 '정상 동작'할 때의 메시지와 '오류 정보' 메시지가 뒤섞여 있는 경우가 많음
여러분이 드라이버에 오류가 있는 코드를 작성해 문제가 발생하면 드라이버 코드가 아니라 리눅스 커널의 코어 함수에서 에러 로그를 출력할 가능성이 높음
커널 디버깅 따라해보기
Kernel Log 분석
- 오류 메시지를 커널 어느 코드에서 출력했는지 확인합니다.
01 void __enable_irq(struct irq_desc *desc)
02 {
03 switch(desc->depth) {
04 case 0:
05 err_out :
06 WARN(1,KERN_WARNING "Unbalanced enable for IRQ %d\n",irq_desc_get_irq(desc));
인터럽트 디스크립터의 자료구조인 irq_desc 구조체의
depth Field는 interrupt를 활성화하면 0, 비활성화하면 1
4번째의 interrupt를 활성화하면 4번째의 interrupt Descriptor의 depth 필드를 0으로 설정함
그런데 6번째 줄 코드는 interrupt를 2번 활성화했을 때 실행됨
interrupt를 활성화했으면 depth 필드가 0인데 다시 활성화해서 경고메시지와 함게 call stack을 출력함
- 소스코드에서 에러 메시지를 출력한 이유를 살펴봐야 한다.
01 WARNING : at kernel/irq/manage.c:225 __enable_irq+0x3b/0x57()
02 Unbalanced enable for IRQ 4
02번째 줄을 보면 "IRQ 4"라는 메시지로 4번 interrupt를 2번 활성화해서 오류 메시지를 출력한 것이다.
위와 같은 에러 메시지는 enable_irq()함수에서 출력한다.
어떤 함수에서 4번 interrupt를 2번 연속으로 활성화하는지 점검해야 한다.
- 필요에 따라 디버깅 코드를 작성해 다시 문제가 발생했을 때 추가 커널 로그 확보를 시도한다.