Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

17312
2027
233850


[리눅스커널] 시그널: 시그널 관련 시스템 호출 함수는 무엇일까? 12. 시그널

시그널을 등록하고 처리하는 동작은 유저 애플리케이션 내에서 실행하는 듯합니다. 하지만 시그널을
설정하고 처리하는 주인공은 커널입니다. 유저 공간에서 시그널 관련 시스템 콜이 발생하면 이를 커널
에서 받아 처리합니다. 커널은 시그널 처리를 위한 다양한 시스템 콜을 지원하며, 시그널 관련 시스템
호출 함수는 다음과 같습니다.

#Referene 시그널
시그널이란
시그널 설정은 어떻게 할까
시그널 생성 과정 함수 분석
프로세스는 언제 시그널을 받을까
시그널 전달과 처리는 어떻게 할까?
시그널 제어 suspend() 함수 분석 
시그널 ftrace 디버깅




[리눅스커널] 드라이버: 셸로 bind와 unbind 명령어를 입력해 probe/remove 함수 호출하기 Linux Kernel - Core Analysis

리눅스 디바이스 드라이버를 플렛폼 디바이스 규칙에 맞게 작성하면 몇 가지 편리한 점이 있습니다.
그 중 하나가 셸 커맨드로 probe/release 함수를 호출할 수 있다는 점입니다.

모듈 타입 디바이스 드라이버를 검증할 때 활용하면 좋을 꿀팁이니, 많은 개발자 분들이 활용했으면 좋겠습니다.

셸 명령어로 디렉터리 확인하기

먼저 /sys/bus/platform/drivers/gpio-keys 디렉터리로 이동합시다.

pi:/sys/bus/platform/drivers # cd gpio-keys/
pi:/sys/bus/platform/drivers/gpio-keys # ls
bind  soc:gpio_keys  uevent  unbind

확인하니 bind와 unbind 파일이 보입니다.

pi:/sys/bus/platform/drivers/gpio-keys # ls -l
total 0
--w------- 1 root root 4096 2018-06-11 03:48 bind
lrwxrwxrwx 1 root root    0 2018-06-11 03:48 soc:gpio_keys -> ../../../../devices/soc/soc:gpio_keys
--w------- 1 root root 4096 2018-06-11 03:48 uevent
--w------- 1 root root 4096 2018-06-11 03:48 unbind

아래와 같은 셸 커맨드를 입력합시다.

pi:/sys/bus/platform/drivers/gpio-keys # echo "soc:gpio_keys" > bind
pi:/sys/bus/platform/drivers/gpio-keys # echo "soc:gpio_keys" > unbind

관련 코드 분석

여기서 'echo "soc:gpio_keys" > bind' 혹은 'echo "soc:gpio_keys" > unbind' 명령어를 입력하면 어떤 함수가 호출될까요? 각각 gpio_keys_probe()/gpio_keys_remove() 함수가 호출됩니다.

다음은 위에서 언급된 함수가 선언된 코드입니다.

https://elixir.bootlin.com/linux/v3.18.140/source/drivers/input/keyboard/gpio_keys.c 
static struct platform_driver gpio_keys_device_driver = {
.probe = gpio_keys_probe,
.remove = gpio_keys_remove,
.driver = {
.name = "gpio-keys",
.owner = THIS_MODULE,
.pm = &gpio_keys_pm_ops,
.of_match_table = of_match_ptr(gpio_keys_of_match),
}
};

커널 크래시 문제 확인

그런데 다음과 같은 명령어를 입력했더니,

pi:/sys/bus/platform/drivers/gpio-keys # echo "soc:gpio_keys" > bind
pi:/sys/bus/platform/drivers/gpio-keys # echo "soc:gpio_keys" > unbind
pi:/sys/bus/platform/drivers/gpio-keys # echo "soc:gpio_keys" > bind

데이터 어보트가 발생하네요.

000|do_DataAbort(?)
-001|__dabt_svc(asm)
 -->|exception
-002|sysfs_remove_file_ns(kobj = 0xFFFFFFF7, attr = 0xC19BEA30, ns = 0x0)
-003|switch_dev_unregister(sdev = 0xC19A1964)
-004|gpio_keys_setup_key(inline)
-004|gpio_keys_probe(?)
-005|platform_drv_probe(_dev = 0xEB490A50)
-006|really_probe(inline)
-006|driver_probe_device(drv = 0xC19A191C, dev = 0xEB490A50)
-007|bind_store(drv = 0xC19A191C, ?, count = 14)
-008|drv_attr_store(?, ?, ?, ?)
-009|sysfs_kf_write(?, buf = 0xC19BEA30, ?, pos = 0)
-010|kernfs_fop_write(?, ?, count = 14, ppos = 0xE1E75F80)
-011|vfs_write(file = 0x0, buf = 0x0, ?, pos = 0xE1E75F80)
-012|SYSC_write(inline)
-012|sys_write(?, buf = -1471503740, count = 14)
-013|ret_fast_syscall(asm)

빨리 문제를 해결해야 겠습니다.

[공유] YES24 판매지수 10,000 돌파: 디버깅을 통해 배우는 리눅스 커널의 구조와 원리 Question_Announcement

제가 쓴 '디버깅을 통해 배우는 리눅스 커널의 구조와 원리' 책의 판매지수(YES24)가 드디어 10,000점을 돌파했습니다. 많은 개발자가 읽다가 포기하는 주제인 '리눅스 커널' 책이 이런 판매 수치가 나온다는 게 신기합니다. 이 모든 것은 리눅스 개발자님과 취준생님들 덕분입니다. 



개발자님들과 취준생 분들에게 많은 도움을 줄 수 있는 실용적인 콘텐츠를 블로그와 유튜브에 꾸준히 올리겠습니다. 감사합니다.

[질문] 11장: vector_swi의 어셈블리 코드에서 스택을 푸시하는 동작 Question_Announcement

질문)

우선 vector_swi의 어셈블리 코드중 첫 번째 라인인 sub sp, sp, #72 부분에서 굳이 sp의 위치를 조절해주는 이유를 모르겠습니다.
그냥 sp에 바로 레지스터 세트들을 push하면 안되는건가요??

또한 스택공간에서 72byte를 확보하는 것도 이해가 잘 가지 않습니다.
분명 저장하는 4byte의 레지스터는 13개 이므로 52byte면 충분하다고 생각합니다. 혹시 다른 용도가 있어서 더 큰 용량을 확보하는 걸까요??


대답)

좋은 질문을 주셨는데요. 

스택공간에서 72 바이트를 확보하는 이유는, 유저 공간에서 실행된 레지스터 세트를 struct pt_regs 구조체로 
관리하기로 약속했기 때문입니다.

pt_regs 구조체 선언부를 보면요.

https://elixir.bootlin.com/linux/v4.19.30/source/arch/arm/include/uapi/asm/ptrace.h
struct pt_regs {
long uregs[18];
};

pt_regs 구조체는 크기가 18인 uregs 배열로 구성돼 있는데, 아래 공식에 따라 72바이트가 됩니다.  

   72 = 4바이트 * 18 

참고로, vector_swi 레이블이 실행될 때의 스택 주소가 0xF1605FB0인 경우,
아래와 같이 레지스터 세트가 푸시됩니다.   
   
   NUD:F1605FB0| 04 00 00 00  0x4          // R0
   NUD:F1605FB4| F8 DD C2 BE  0xBEC2DDF8   // R1
   NUD:F1605FB8| 01 00 00 00  0x1         // R2     
   NUD:F1605FBC| FF FF FF FF  0xFFFFFFFF   // R3
   NUD:F1605FC0| 00 00 00 00  0x0    // R4
   NUD:F1605FC4| 08 00 00 00  0x8       // R5        
   NUD:F1605FC8| 00 00 00 00  0x0    // R6
   NUD:F1605FCC| 5A 01 00 00  0x15A        // R7  
   NUD:F1605FD0| 38 71 11 00  0x117138    // R8 
   NUD:F1605FD4| 14 71 11 00  0x117114    // R9 
   NUD:F1605FD8| 14 71 11 00  0x117114    // R10 
   NUD:F1605FDC| 34 50 11 00  0x115034    // R11 
   NUD:F1605FE0| 50 DD C2 BE  0xBEC2DD50   // R12 
   NUD:F1605FE4| 40 DD C2 BE  0xBEC2DD40   // R13
   NUD:F1605FE8| C9 52 0C 00  0xC52C9      // R14
   NUD:F1605FEC| B4 96 0C 00  0xC96B4      // PC
   NUD:F1605FF0| 10 00 07 60  0x60070010   // CPSR  
   NUD:F1605FF4| 04 00 00 00  0x4          // ORIG_r0

TRACE32로 0xF1605FB0 주소를 pt_regs 구조체로 캐스팅하면, 다음과 같은 정보를
확인할 수 있습니다.   
   
  (struct pt_regs *) (struct pt_regs*)0xF1605FB0 = 0xF1605FB0 -> (
    (long unsigned int [18]) uregs = (
      [0] = 4 = 0x4,
      [1] = 3200441848 = 0xBEC2DDF8,
      [2] = 1 = 0x1,
      [3] = 4294967295 = 0xFFFFFFFF,
      [4] = 0 = 0x0,
      [5] = 8 = 0x8,
      [6] = 0 = 0x0,
      [7] = 346 = 0x015A,
      [8] = 1143096 = 0x00117138,
      [9] = 1143060 = 0x00117114,
      [10] = 1143060 = 0x00117114,
      [11] = 1134644 = 0x00115034,
      [12] = 3200441680 = 0xBEC2DD50,
      [13] = 3200441664 = 0xBEC2DD40,
      [14] = 807625 = 0x000C52C9,
      [15] = 825012 = 0x000C96B4,
      [16] = 1611071504 = 0x60070010,
      [17] = 4 = 0x4))

이와 같은 패턴으로 유저 공간에서 실행된 레지스터 세트를 관리합니다.


[IT] 임베디드 BSP 개발자들은 언제 가장 답답해할까? 임베디드 에세이

임베디드 BSP 개발자들은 언제 답답함을 느낄까요? 
야근을 할 때 일까요? 사채업자와 같은 매니저가 찾아와 목에 칼을 들이 대면서 말도 안되는 일정으로 윽박지를 때인가요?
이런 상황은 짜증이 조금 나긴 하지만 그나마 버틸만 합니다.

임베디드 BSP 개발을 진행하다가 가장 암담함을 느낄 때는, 뭘 배우고 공부를 해야 실력을 키울 수 있을 지 모를 때입니다. 실력을 키우는 방법을 모르는 상황이죠. 아마 안개 속에서 보이지 않는 적과 싸우는 느낌일텐데요.

이런 임베디드 BSP 개발자가 어떻게 하면 실력을 키우는 되는지 주위 선배들에게 물어 보면 속 시원하게 대답을 해주지도 못합니다.

위에서 언급된 임베디드 BSP 개발자가 저였습니다. 이런 암담함을 초보 개발자 시절에 3년 정도 겪었습니다. 개발 도중에 크래시가 발생하면 매니저는 "옥상에서 뛰어 내리라고 했는데, 그 때 가장 답답했던 것은 "뭘 배워야 욕을 덜 먹을지 몰랐다"는 점이었습니다.

(그 당시 트라우마가 아직도 남아 있어, 저는 옥상에 잘 가지 않습니다.)

시간이 지나고 보니, 임베디드 BSP 개발자로써 실력을 키우기 위해 배워야 할 지식이 무엇인지 천천히 알게 됐습니다. 그 목록을 정리하면 다음과 같습니다.

   * 디버깅 스킬(TRACE32 혹은 하드웨어 디버거)
   * Arm 아키텍처(특히 익셉션, 메모리 시스템)
   * SoC에 대한 지식(특히 Stability Architecture, Boot Sequence)
   * 리눅스 커널

'디버깅을 통해서 배우는 리눅스 커널의 구조와 원리' 전체 목차 -----Table of Contents-----

@ 리눅스 개발자분들께...

제 블로그에 오셔서 댓글로 책이 언제 출간되는지 궁금해하시는 분이 계신 것 같은데요.

아래 링크에서 만나실 수 있습니다.  이 책은 리눅스 개발에 도움이 되는 유용한 내용을 담고 있으니, 많은 리눅스 시스템 개발자분들이 읽어 주셨으면 좋겠습니다.

❑ 디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

❑ 디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2

이 책의 주요 독자는 신입 개발자 혹은 졸업반 학생과 같은 리눅스 커널의 입문자이며 세부 예상 독자는 다음과 같습니다.

▣ 리눅스 보드로 졸업 과제를 준비 중인 졸업반 학생
▣ 연구실의 프로젝트를 리눅스 환경(리눅스 보드, 리눅스 배포판)에서 진행 중인 대학원생
▣ 리눅스 드라이버의 동작 원리를 더 깊게 알고 싶은 분
▣ 리눅스 커널을 실무에서 어떻게 디버깅하는지 알고 싶은 리눅스 시스템 개발자

# 책 디자인 스틸 컷은 다음과 같습니다. 
 


아래 링크와 같이 유튜브 강의 동영상을 업로드를 하니 책을 읽으면서 들으시면 좋습니다.



디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

리눅스의 전망과 소개


라즈베리 파이 설정 

라즈베리 파이 설치하기
라즈베리 파이 기본 설정하기 
라즈비안 리눅스 커널 빌드


리눅스커널 디버깅


프로세스

프로세스 소개 
프로세스 확인하기  
프로세스는 어떻게 생성할까?  
유저 레벨 프로세스 실행 실습  
커널 스레드  
커널 내부 프로세스의 생성 과정   
프로세스의 종료 과정 분석  
태스크 디스크립터(task_struct 구조체)  
스레드 정보: thread_info 구조체  
프로세스의 태스크 디스크립터에 접근하는 매크로 함수  
프로세스 디버깅  
   * glibc의 fork() 함수를 gdb로 디버깅하기  

인터럽트 처리

인터럽트 소개  
   * 리눅스 커널에서의 인터럽트 처리 흐름    
인터럽트 컨텍스트  
인터럽트 핸들러는 언제 호출될까?  
인터럽트 핸들러는 어떻게 등록할까?  
인터럽트 디스크립터  
인터럽트 디버깅  


인터럽트 후반부 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  

워크큐

워크큐 소개
워크큐 종류 알아보기
워크란  
워크를 워크큐에 어떻게 큐잉할까?
   워크를 큐잉할 때 호출하는 워크큐 커널 함수 분석   
워커 쓰레드란
워크큐 실습 및 디버깅
   ftrace로 워크큐 동작 확인   
   인터럽트 후반부로 워크큐 추가 실습 및 로그 분석 
   Trace32로 워크큐 자료 구조 디버깅하기 
딜레이 워크 소개  
   딜레이 워크는 누가 언제 호출할까?
라즈베리파이 딜레이 워크 실습 및 로그 확인  


디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2

커널 시간관리

커널 타이머 관리 주요 개념 소개
jiffies란
커널 타이머 제어
동적 타이머 초기화
동적 타이머 등록하기
동적 타이머는 누가 언제 실행하나?
라즈베리파이 커널 타이머 실습 및 로그 분석
   
커널 동기화

커널 동기화 기본 개념 소개
레이스 발생 동작 확인
커널 동기화 기법 소개
스핀락
뮤텍스란
커널 동기화 디버깅

프로세스 스케줄링

스케줄링 소개
프로세스 상태 관리
   어떤 함수가 프로세스 상태를 바꿀까?
스케줄러 클래스
런큐
CFS 스케줄러
   CFS 관련 세부 함수 분석  
선점 스케줄링(Preemptive Scheduling)   
프로세스는 어떻게 깨울까?
스케줄링 핵심 schedule() 함수 분석
컨택스트 스위칭
스케줄링 디버깅
   스케줄링 프로파일링
     CPU에 부하를 주는 테스트   
     CPU에 부하를 주지 않는 테스트 

시스템 콜

시스템 콜 주요 개념 소개
유저 공간에서 시스템 콜은 어떻게 발생할까
시스템 콜 핸들러는 어떤 동작을 할까? 
시스템 콜 실행 완료 후 무슨 일을 할까?
시스템 콜 관련 함수  
시스템 콜 디버깅  
   

시그널이란

시그널이란
시그널 설정은 어떻게 할까
시그널 생성 과정 함수 분석


가상 파일시스템

가상 파일시스템 소개
파일 객체
파일 객체 함수 오퍼레이션 동작
프로세스는 파일객체 자료구조를 어떻게 관리할까?
슈퍼블록 객체
아이노드 객체
덴트리 객체
가상 파일시스템 디버깅


커널 메모리 관리
 
가상 주소를 물리 주소로 어떻게 변환할까?   
메모리 존(Zone)에 대해서   
커널 메모리 할당은 어떻게 할까   
슬랩 메모리 할당자와 kmalloc 슬랩 캐시 분석   
커널 메모리 디버깅


[부록 A] GCC 지시어
   * inline    
   * noinline    
   * __noreturn   
   * unused   
[부록 B] 리눅스 커널 실력을 키우는 방법
[부록 C] 리눅스 커널 프로젝트에 기여하기  
C.1 리눅스 커널 오픈소스 프로젝트 소개 
   * 용어  
C.2 설정 방법 
C.3 패치 코드를 작성한 후 이메일로 보내기  
C.5 리눅스 커널 오픈소스 프로젝트로 얻는 지식 


[GDB] Arm(Armv7): C 코드와 어셈블리 코드를 동시에 디버깅하기 [Debugging] Tips

이번 포스트에서는 GDB를 사용해 디버깅을 하는 방법을 소개합니다. 소개된 내용을 참고하면 즐겁게 어셈블리 명령어를 디버깅할 수 있습니다.

환경: 라즈베리 파이4

GDB 실행

아래 명령어를 사용해 GDB를 Text User Interface 모드로 실행합니다.

$ gdb -tui armv7_aapcs_proc

다음은 위 명령어로 실행한 화면입니다.


이제 바로 다음 명령어를 입력해 어셈블리 명령어 창을 보이도록 합시다.

$ layout split



이번에는 'b main'와 'r' 명령어를 입력해 main() 함수에 브레이크 포인트를 걸고 프로그램을 실행합니다.



위 명령어를 입력하면 다음과 같은 화면이 보입니다.



위 화면과 같이 main() 함수의 첫 번째 라인에 브레이크 포인트가 걸립니다.

C 코드 한 줄 실행

자, 이어서 'n' 명령어를 입력해 C 코드 기준으로 소스 한 줄을 실행합시다.


C 코드 기준으로는 19번째 줄, 어셈블리 코드 기준으로 0x10490 주소까지 실행됐습니다.

어셈블리 명령어 기준 실행

이번에는 'si' 명령어를 입력해 어셈블리 코드를 라인 바이 라인(line-by-line)으로 실행합시다.


특이한 점은 어셈블리 코드 기준으로 브레이크 포인트가 움직이는데, C 소스 기준으로 브레이크 포인트는 변하지 않을 때가 많다는 점입니다. 이는 C 코드 1줄을 2~3개 어셈블리 명령어로 실행하기 때문입니다.

레지스터 창 출력하기 

이번에는 레지스터 정보를 확인하기 위해 'info reg' 명령어를 입력합시다.


SP(스택 포인터) 레지스터는 0xbefff5d0, LR(링크 레지스터)는 0xb6e6a718 주소를 저장합니다.

레지스터를 확인하기 위해 'layout reg' 명령어를 입력해 보겠습니다.


레지스터와 어셈블리 명령어가 출력됩니다. 이 상태로 계속 디버깅을 할 수 있으나, C 코드가 보이지 않으니 조금 답답합니다. 이 때 'layout split' 명령어를 다시 입력하면 C 코드와 어셈블리 명령어를 같이 볼 수 있는 창으로 변환됩니다.

이번에도 'si' 명령어를 입력해 어셈블리 명령어 'ldr    r0, [r11, #-8]'를 실행합니다.


이제 'bl     0x10434 <add_func>' 명령어를 실행해 add_func() 함수를 호출하기 직전의 시점입니다.

Armv7 아키텍처의 동작 원리를 배우며 디버깅해보기

여기서 한 가지 눈여겨 볼 부분이 있습니다. 'bl     0x10434 <add_func>' 명령어 아랫 부분의 주소가 0x104a4인데 add_func() 함수를 호출하면 복귀할 주소입니다.

그런데 add_func() 함수가 실행해 add_func() 함수의 시작 주소로 PC가 바뀌면 lr은 0x104a4 주소로 바뀔 것입니다. 이 점을 예상하고 'bl     0x10434 <add_func>' 명령어를 실행하기 직전의 레지스터 정보를 확인해 봅시다. (이를 위해 'info reg' 명령어를 입력했습니다.)

확인하니 lr(r14) 레지스터는 0xb6e6a718를 담고 있습니다.

이번에는 si 명령어를 입력해 'bl     0x10434 <add_func>' 명령어를 실행하겠습니다.


위 화면과 같이 add_func() 함수의 첫 번째 코드에 브레이크 포인트가 걸려 있습니다.

자, 이 시점에서 lr(r14) 레지스터를 확인해볼까요? 확인하니 lr(r14) 레지스터는 0xb6e6a718를 담고 있습니다.

이 방법을 활용해 GDB를 실행하면, Arm 어셈블리 명령어를 실행하면 레지스터가 어떻게 바뀌는지 직접 눈으로 확인할 수 있습니다.

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자






[IT] 개발자로써 자기계발을 하기 어려운 이유 - 1 임베디드 에세이

종종 현업 개발자들이랑 만나면, 듣는 이야기가 있습니다.

   "개발자로써 커리어를 관리하기 어렵다."
   "지금 하고 있는 개발 스킬을 다른 회사에서 활용할 수 있을까?"

개발자들끼리 조금 진지하게 대화를 나누면 나오는 주제입니다. 물론 저도 이런 고민을 수도 없이 했는데요. 종종 "개발자로써 커리어를 관리하기 어려운 이유가 무엇인가"에 대해 생각해 봤습니다. 가끔은 다른 회사의 임원이나 관리자분들을 만날 기회가 있었는데, 그 분들과 대화를 나누니 무엇인가 퍼즐이 맞춰진다는 느낌을 받았습니다.

그 퍼즐은 바로 "개발자의 커리어 관리"입니다.

많은 분들이 취준생들에게 어찌보면 포괄적이고 두루뭉실한 조언을 많이 합니다. 그것은;

    "열심히 노력해라. 노력한 만큼 보상이 주어지는 게 소프트웨어 개발이다."
    "개발자로써 실력을 키우도록 노력해라."

틀린 말은 아니지만, 저에겐 뭔가 공허한 소리로만 들리는데요. 그 이유에 대해 조금 더 말씀드리겠습니다.

개발자들은 부서장들의 성과를 위해서만 존재한다

개발자로써 커리어를 관리하고 키우기 전에 먼저 알아야 할 핵심이 있습니다.

   "개발자들은 부서장들의 성과를 위해서만 존재한다."

한국에 있는 대부분의 IT 회사들은 위에서 언급한 규칙에 따라 움직이게 되어 있습니다. 여러분들은 여러분의 상사를 위해 존재한다는 말입니다. 이런 문장을 읽으면 물론 불쾌한 느낌이 들기 마련인데요. 조금은 듣기는 거북해도 맞는 말이란 생각이 듭니다. 쓴 약이 몸에도 좋다는 말이 있잖아요.

매니저들이나 부서장(대부분 개발자들의 상사)들은 개발자들에게 다음과 같이 조언합니다.
 
   "개발자로써 역량을 키우는게 중요하다."  

개발자들이 매니저에게 이런 말을 들으면 "그래, 개발자로써 실력을 키우는 게 중요하지. 열심히 공부해야 겠다"란 생각이 들 것입니다. 그런데 부서장들의 속 마음을 디버깅해보면 그들이 정말로 하고 싶은 메시지는 다음과 같습니다.

   " (나의 성과를 위해) 개발자로써 역량을 키우는게 중요하다."  

부서장 입장에서는 자신의 성과를 달성하는게 가장 중요합니다. 첫 째도 성과, 두 번째도 성과입니다. 이를 위해 필요한 조건 중의 하나가 개발 역량인 겁니다. 그런데 부서장은 한술 더 떠서 다음과 같은 이야기를 합니다.

   " 개발자로써 전문성을 유지하고 키워나가는 게 중요하다."  

하지만 이들의 속마음을 들여다보면 "나의 성과를 이루기 위해 내 부서에 있는 개발자들이 전문성을 키웠으면 한다" 진심입니다.

니가 나를 위해 일하지 않고, 니가 크려고 해!

그런데 가끔 개발자 중에 전문성을 키우다가 "개발자가 소속된 부서의 성과"를 내는 것 이상의 실력을 키우는 경우도 있습니다. 개발자로써 역량을 끌어올리다 보니 전문성이 계속 증진되는 경우입니다.

예를 들면, 리눅스 커널에 컨트리뷰션(기여)를 한다던가, 컴파일러 코드를 개선해 뭔가 성능을 개선하는 것을 들 수 있습니다. 가끔은 공부한 내용을 잘 정리해 책을 출간하기도 합니다.

그런데 거의 대부분의 부서장들은 자신의 성과에 직접적인 결실을 맺을 수 없는 개발 역량을 키우는 것 별로 좋아 하지 않습니다. 물론 책을 쓰는 것을 싫어하는 분들도 많습니다.(이 사실을 제가 출판사 사장님께도 들은 내용입니다.) 그 이유는 간단합니다.

    "자신을 위해 일을 하지 않기 때문입니다."

부서장들은 자신도 모르게 이런 생각이 들 겁니다.

   "니가 나를 위해 일하지 않고, 니가 크려고 해!"
   "그건 내가 용납할 줄 알아" 

극단적으로 말해, 부서장은 자신의 성과를 위해 개발자 여러분이 어떤 개발 역량을 갖추었는지 관심을 갖습니다. 자신의 성과를 위해 여러분이 존재할 뿐인 것이죠.

대부분 IT 업체는 부서장의 성과를 중심으로 운영됩니다. 이 점을 염두에 두면 그 동안 이해되지 않았던 많은 부분이 명쾌해질 것입니다.

[공지] 이북(Ebook) 출간: '디버깅을 통해 배우는 리눅스 커널의 구조와 원리' 1부 Question_Announcement

안녕하세요, '디버깅을 통해 배우는 리눅스 커널의 구조와 원리' 저자 김동현입니다.

리눅스 시스템 개발자와 취준생님, 대학원생님들께...

많은 리눅스 시스템 개발자 분들이 '디버깅을 통해 배우는 리눅스 커널의 구조와 원리' 이북이 출간되기를 기다리셨는데요. 
드디어 3월에 이북(Ebook)이 출간됩니다.

1부와 2부가 동시에 출간되는 것은 아니고요, 1부가 먼저 출간됩니다.
참고로, 2부는 올해 5월 달에 출간이 예정되어 있습니다.

이 책의 강의 동영상과 리눅스 디버깅과 Arm 프로세서에 대한 유익한 콘텐츠가 개인 유튜브 채널에도 업로드되어 있으니 많이 참고하셨으면 좋겠습니다.


즐거운 한 주 보내세요.

감사합니다.
김동현 드림.


[리눅스] 프로세스를 지정한 CPU에서 실행: sched_setaffinity() 함수 Linux Kernel - Core Analysis

소형 임베디드 장비를 제외하고는 대부분 시스템은 멀티 CPU 코어 환경에서 개발됩니다. 
멀티 프로세스(Multiprocess) 기반으로 작성된 데몬을 실행하면 여러 CPU 코어에 적당히 나뉘어 실행되는 것을 쉽게 볼 수 있습니다. CPU0에서 실행됐다가 CPU2에서 실행되는 것이죠.

그런데 가끔은 특정 작업을 수행하는 프로세스가 특정 CPU 코어에서 실행되도록 설정해야 할 때가 있습니다. 여러가지 이유가 있지만 요약하면 다음과 같습니다.

    * 실행하는 프로세스와 관련된 인터럽트가 특정 CPU 코어에서만 트리거됨(IRQ Affinity라고 하죠.)
    * 프로세스가 여러 CPU 코어에 옮겨 다니면서 실행할 때 요구되는 오버헤드(마이그레이션)을 최소화하자

참고로 커널이 프로세스를 어떤 CPU 코어에 할당하는지는, 커널 내부의 자체적인 스케쥴링 메카니즘에 따라 결정됩니다. 

간단한 예제 코드로 실습하기

이어서 다음 코드를 보면서 설명을 이어나겠습니다.
 
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/wait.h>
 
int main(void) 
{
unsigned int i = 0;
pid_t pid;
 
if ((pid = fork()) == 0 ) {
for ( i = 0; i < UINT_MAX; i++) {
printf("I am running\n");
}
}
else {
int status;
waitpid(pid, &status, 0);
}
 
return EXIT_SUCCESS;
}

위 소스는 1개의 자식 프로세스를 생성하고 더하기 연산을 반복적으로 수행하여 CPU를 100% 사용하게 만드는 예제입니다. 

위 코드를 작성한 후 raspbian_test.c 이란 이름으로 저장합니다. 이어서 다음 구문을 입력해 Makefile을 생성합니다.

#Makefile
raspbian_proc: raspbian_test.c
gcc -o raspbian_proc raspbian_test.c

Makefile을 만든 다음에 make를 입력하면 raspbian_test.c을 손쉽게 컴파일할 수 있습니다.
아래는 make 명령어를 입력한 후의 터미널 출력 결과입니다.

root@raspberrypi:/home/pi/work/test_affinity# make
gcc -o raspbian_proc raspbian_test.c

이어서 ./raspbian_proc 명령어를 입력해 작성한 코드를 실행합니다.

root@raspberrypi:/home/pi/work/test_affinity# ./raspbian_proc 
I am running
I am running
I am running

예제 코드 실행 결과 분석하기

터미널을 하나 더 열어 top을 실행시킨 후 '1'번 키를 눌러 CPU 별로 사용량을 지켜볼 수 있게 준비를 합니다. 

root@raspberrypi:/home/pi# top
top - 10:27:42 up 51 min,  5 users,  load average: 2.20, 0.72, 0.26
Tasks: 146 total,   6 running, 140 sleeping,   0 stopped,   0 zombie
%Cpu0  : 12.9 us, 49.4 sy,  0.0 ni, 33.2 id,  0.0 wa,  0.0 hi,  4.4 si,  0.0 st
%Cpu1  : 16.4 us, 55.5 sy,  0.0 ni, 26.7 id,  0.0 wa,  0.0 hi,  1.4 si,  0.0 st
%Cpu2  :  7.1 us, 59.1 sy,  0.0 ni, 33.8 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  :  4.5 us, 36.0 sy,  0.0 ni, 57.4 id,  0.0 wa,  0.0 hi,  2.1 si,  0.0 st
MiB Mem :   1939.5 total,   1494.6 free,     93.7 used,    351.1 buff/cache
MiB Swap:    100.0 total,    100.0 free,      0.0 used.   1662.1 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
  132 root      20   0   45984  17828  16852 S   99.3   0.9   0:33.90 raspbian_proc

그리고, 소스를 컴파일 해서 여러번 실행시켜 보면 사용량이 100%에 달하는 CPU가 고정적이지 않고 변하는 것을 확인 할 수 있습니다. 

이번에는 ftrace 메시지를 통해 위 코드가 실행될 때 CPU 코어의 번호를 확인해 보겠습니다. 아래 ftrace 메시지를 볼까요? 

raspbian_proc-1106  [002] d...  4086.493934: sched_switch: prev_comm=raspbian_proc prev_pid=1 106 prev_prio=120 prev_state=R+ ==> next_comm=kworker/u8:2 next_pid=1019 next_prio=120
...
raspbian_proc-1106  [001] d...  4086.583273: sched_switch: prev_comm=raspbian_proc prev_pid=1 106 prev_prio=120 prev_state=R+ ==> next_comm=kworker/u8:0 next_pid=1084 next_prio=120

4086.493934 초에는 2번째 CPU 코어에서 실행하다가, 4086.583273초에는 1번째 CPU 코어에서 해당 코드가 실행 중이란 사실을 알 수 있습니다. 

sched_setaffinity() 함수를 사용해 CPU 코어를 지정하는 예시 코드

이번에는 해당 프로세스를 특정 CPU 코어에서 실행하는 예제 코드를 소개합니다.

#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <getopt.h>
#include <sched.h>
 
void print_help(char *cmd) {
printf("Usage: %s -n <cpu 개수> -c < 선호CPU>\n\n", cmd);
printf(" CPU 개수 : CPU 코어 개수\n");
printf(" 선호 CPU : CPU 코어 번호 (0 부터 시작)\n\n");
printf(" 예 : 쿼드코어 CPU에서 3번째 코어를 사용하는 경우\n");
printf(" $ %s -n 4 -c 2\n", cmd);
}
 
int main(int argc, char *argv[]) {
unsigned int i = 0;
pid_t pid;
int max_cpu = -1;
int cpu = -1;
int opt;
 
while ( (opt = getopt(argc, argv, "n:c:")) != -1 ) {
switch ( opt ) {
case 'c' :
cpu = atoi(optarg);
printf("cpu: %d \n", cpu);
break;
case 'n' :
max_cpu = atoi(optarg);
printf("max_cpu: %d \n", max_cpu);
break;
case '?' :
default :
print_help(argv[0]);
exit(EXIT_FAILURE);
break;
}
}
printf("@: %d \n", __LINE__);
if ( max_cpu < 1 || cpu < 0 || cpu >= max_cpu ) {
print_help(argv[0]);
printf("@: %d \n", __LINE__);
exit(EXIT_FAILURE);
}
 
if ( (pid = fork()) == 0 ) {
cpu_set_t mask;
printf("@: %d \n", __LINE__);
 
CPU_ZERO(&mask);
CPU_SET(cpu, &mask);
 
pid = getpid();
if ( sched_setaffinity(pid, sizeof(mask), &mask) ) {
fprintf(stderr, "%d 번 CPU를 선호하도록 설정하지 못했습니다.\n", cpu);
exit(EXIT_FAILURE);
}
else {
printf("%d 번 CPU를 선호하도록 설정했습니다.\n", cpu);
}
 
for ( i = 0; i < UINT_MAX; i++) {
}
}  else {
int status;
waitpid(pid, &status, 0);
}
 
return EXIT_SUCCESS;
}
 
위 소스 코드는 sched.h에서 제공하는 sched_setaffinity() 함수를 사용하여 특정한 CPU에서 프로세스가 실행되도록 한 것입니다.
 
sched_setaffinity() 함수는 3개의 매개변수를 받는데 첫번째는 프로세스 ID(pid)입니다. pid 대신 0을 넘기면 자동으로 현재 동작중인 프로세스로 설정됩니다. 두 번째는 cpusetsize 입니다. 보통은 sizeof(cpu_set_t)로 설정하면 됩니다. 세번째는 mask 포인터입니다. mask 포인터는 아래의 매크로 함수들을 사용해서 편리하게 설정 할 수 있습니다.

위 코드를 컴파일한 다음에 다음 명령어를 입력해 실행해 볼까요?

root@raspberrypi:/home/pi/work/test_affinity# ./raspbian_proc -n 4 -c 0
max_cpu: 4
cpu: 0
@: 49
@: 59
0 번 CPU를 선호하도록 설정했습니다.

전체 CPU 코어의 갯수는 4, 지정하려는 CPU 번호는 0으로 설정해 실행했습니다.

로그 분석

아래는 위 코드를 실행한 후 확인한 ftrace 메시지입니다.

raspbian_proc-1177  [000] d...  4556.349390: sched_switch: prev_comm=raspbian_proc prev_pid=1177 prev_prio=120 prev_state=R ==> next_comm=irq/36-mmc1 next_pid=83 next_prio=49
raspbian_proc-1177  [000] d...  4556.454209: sched_switch: prev_comm=raspbian_proc prev_pid=1177 prev_prio=120 prev_state=R ==> next_comm=kworker/0:0 next_pid=1142 next_prio=120
kworker/0:0-1142  [000] d...  4556.454225: sched_switch: prev_comm=kworker/0:0 prev_pid=1142 prev_prio=120 prev_state=D ==> next_comm=raspbian_proc next_pid=1177 next_prio=120

보다시피, 0번째 CPU에서 위 코드가 실행했다는 사실을 알 수 있습니다.
 
cpu는 CPU의 번호로 0번부터 시작합니다. 쿼드코어 CPU를 탑재한 라즈베리 파이에서는 0~3번 사이의 값이 됩니다. 또한 mask 값을 여러개의 CPU로 지정하는 것도 가능합니다.

참고로 아래는 CPU 코어를 설정하는데 필요한 함수 목록입니다.
 
 void CPU_CLR(int cpu, cpu_set_t *set);
 int CPU_ISSET(int cpu, cpu_set_t *set);
 void CPU_SET(int cpu, cpu_set_t *set);
 void CPU_ZERO(cpu_set_t *set);

정리

멀티프로세스나 멀티쓰레드를 여러개의 CPU나 코어에 적절히 배치하여 효과적으로 사용하는 것은 매우 어려운 기술입니다. sched_setaffinity 함수를 통해 수동으로 배치했다고 해서 그것이 반드시 커널의 스케줄러에 의해 선택되는 동작보다 효율적이라는 보장은 없습니다.
 
다만 몇가지 특징적인 프로세스들을 적절히 배치하여 CPU 자원을 어느 정도 보장 해주는데 도움이 될 수 있습니다.

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자





다음 포스트에서는 sched_setaffinity() 함수를 유저 프로세스에서 실행하면 커널에서 어떤 방식으로 처리되는지 소개합니다.

[리눅스] /proc/meminfo 메모리 정보 해석하기 14. 메모리 관리

보통 시스템에 메모리가 얼마나 남아 있는지 점검하고 싶을 때가 있어요. 이런 상황에서 메모리를 디버깅할 때 가장 많이 활용되는 파일이 '/proc/meminfo'입니다.

cat "/proc/meminfo" 명령어를 치면 상세한 메모리 정보를 파악할 수 있거든요.
이번에는 "/proc/meminfo"란 노드가 proc 파일 시스템에 메모리 정보를 어떻게 읽어 오는 지 소개합니다. 

/proc/meminfo 해석

'cat /proc/meminfo' 명령어를 입력하면 출력되는 결과와 관련 정보는 다음과 같습니다. 

root@raspberrypi:/home/pi# cat /proc/meminfo
MemTotal:        1986000 kB    // 전체 물리 메모리크기     (1986000 kB/1024 = 1939MB)
MemFree:         1506308 kB    // 사용 가능한 메모리 크기 (1506308 kB/1024 =  1471MB)
MemAvailable:    1694404 kB   
Buffers:           31308 kB       // 디스크 접근용 버퍼 크기(파일 시스템용 메타데이터)
Cached:           257216 kB     // 페이지 캐시 사이즈
SwapCached:            0 kB     // 스왑 중인 페이지 사이즈
SwapTotal:       945532 kB // 전체 스왑 영역 크기
SwapFree:        664176 kB // 사용 가능한 스왑
Active:           203072 kB       // active LRU 크기
Inactive:         171568 kB      // inactive LRU 크기
Active(anon):      86532 kB    // active-anon LRU
Inactive(anon):    41124 kB    // inactive-anon LRU
Active(file):     116540 kB      // active-file LRU
Inactive(file):   130444 kB      // inactive-file LRU
Unevictable:          16 kB      // 회수불가능한페이지
Mlocked:              16 kB      // mlock() 시스템 콜로 lock 걸린 페이지
HighTotal:       1232896 kB   // 전체 High 메모리(유저 스페이스에서 접근) 크기
HighFree:         878004 kB    // 사용 가능한 High 메모리(유저 스페이스에서 접근) 크기
LowTotal:         753104 kB    // 전체 Low 메모리 크기(커널에서 엑세스)
LowFree:          628304 kB    // 사용 가능한 Low 메모리 크기(커널에서 엑세스)
SwapTotal:        102396 kB
SwapFree:         102396 kB
Dirty:               596 kB         // 디스크에 기록해야 할 페이지
Writeback:             0 kB       // 디스크에 기록 중인 페이지
AnonPages:         86152 kB    // 익명 매핑된 사용자 페이지
Mapped:            95420 kB    // 파일 매핑된 사용자 페이지 
Shmem:             41536 kB    // 공유 메모리 페이지
Slab:              55408 kB       // 슬랩 할당자가 관리하는 커널 페이지
SReclaimable:      24300 kB   // 회수 가능한 슬랩 페이지 
SUnreclaim:        31108 kB    // 회수 불가능한 슬랩 페이지
KernelStack:        1856 kB     // 커널 스택으로 사용 중인 페이지
PageTables:         4308 kB    // (하위) 페이지 테이블로 사용 중인 페이지
NFS_Unstable:          0 kB     // NFS에서 사용
Bounce:                0 kB       // 디스크 장치에서 사용 
WritebackTmp:          0 kB    // FUSE 파일시스템에서 사용
CommitLimit:     1095396 kB  // 오버커밋이 허용된 크기(/proc/sys/vm/overcommit_memory 확인 필요)
Committed_AS:     911844 kB  // 실제 오버 커밋된 가상 메모리의 크기
VmallocTotal:     245760 kB    // 전체 vmalloc영역의 크기
VmallocUsed:           0 kB      // 실제로 할당된 vmalloc 영역
VmallocChunk:          0 kB     // 사용 가능한 가장 큰 vmalloc 영역의 크기
Percpu:              640 kB
CmaTotal:         262144 kB
CmaFree:          239556 kB

갑자기 시스템의 메모리 정보를 확인해야 할 때 바로 확인하면 좋은 정보인 것 같습니다.

그런데 이 정보를 보면 한 가지 의문이 생깁니다.

    "이 정보를 출력해 주는 주인공은 누구일까?" 

리눅스 시스템 어딘가에서 이 정보를 출력할텐데요. 그 주인공은 리눅스 커널입니다. 이어서 /proc/meminfo 파일을 통해 시스템 메모리 정보를 출력하는 커널 코드를 소개합니다.

메모리 정보를 출력하는 커널 코드 분석 

우선 커널이 부팅하는 과정에서 아래 함수에서 meminfo란 이름으로 proc 파일 시스템으로 등록합니다. 

https://elixir.bootlin.com/linux/v4.19.30/source/fs/proc/meminfo.c
static int __init proc_meminfo_init(void)
{
proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
return 0;
}

static int meminfo_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, meminfo_proc_show, NULL);
}

static const struct file_operations meminfo_proc_fops = {
.open = meminfo_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};

아래 코드를 보면 meminfo_proc_show() 함수에서 메모리 세부 정보를 출력한다는 사실을 알 수 있습니다.

static int meminfo_proc_show(struct seq_file *m, void *v)
{
struct sysinfo i;
unsigned long committed;
long cached;
...
show_val_kb(m, "MemTotal:       ", i.totalram);
show_val_kb(m, "MemFree:        ", i.freeram);
show_val_kb(m, "MemAvailable:   ", available);
show_val_kb(m, "Buffers:        ", i.bufferram);
show_val_kb(m, "Cached:         ", cached);
show_val_kb(m, "SwapCached:     ", total_swapcache_pages());
show_val_kb(m, "Active:         ", pages[LRU_ACTIVE_ANON] +
   pages[LRU_ACTIVE_FILE]);
show_val_kb(m, "Inactive:       ", pages[LRU_INACTIVE_ANON] +
   pages[LRU_INACTIVE_FILE]);
show_val_kb(m, "Active(anon):   ", pages[LRU_ACTIVE_ANON]);
show_val_kb(m, "Inactive(anon): ", pages[LRU_INACTIVE_ANON]);
show_val_kb(m, "Active(file):   ", pages[LRU_ACTIVE_FILE]);
show_val_kb(m, "Inactive(file): ", pages[LRU_INACTIVE_FILE]);

가끔 메모리 leak으로 이슈가 생길 경우 섬세한 디버깅 패치를 작성해서 메모리가 어느 시점에 변동되는지 점검해야 하거든요. 5초 간격으로 호출되는 간단한 타이머 함수를 호출해서 메모리 잔여량을 체크하는 함수를 작성하는거죠.

이 때 proc 파일 시스템으로 등록된 meminfo_proc_show 내에서 호출된 함수 조각을 잘 활용하면 매우 유용할 것 같아요. 아래 함수로 High 메모리 잔여양과 전체 High Memory 양을 확인할 수 있어요.

https://elixir.bootlin.com/linux/v4.19.30/source/mm/page_alloc.c
void si_meminfo(struct sysinfo *val)
{
val->totalram = totalram_pages;
val->sharedram = global_page_state(NR_SHMEM);
val->freeram = global_page_state(NR_FREE_PAGES);
val->bufferram = nr_blockdev_pages();
val->totalhigh = totalhigh_pages;
val->freehigh = nr_free_highpages();
val->mem_unit = PAGE_SIZE;
}

전체 low memory 양은 val->totalram - val->totalhigh,
free low memory 양은 val->freeram -  val->freehigh 으로 계산할 수 있죠.

아래 메모리 정보는 아래 정보로 계산이 되니 아래 API를 참고해서 시간에 따라 메모리가 얼마나 남아 있는지 체크해도 좋을 것 같아요.

"MemTotal:       %8lu kB\n" // val->totalram
"MemFree:        %8lu kB\n" // val->freeram
"MemAvailable:   %8lu kB\n" // val->freeram + 페이지 캐시 + global_page_state(NR_SLAB_RECLAIMABLE)
"Buffers:        %8lu kB\n" // val->bufferram
"Cached:         %8lu kB\n" // global_page_state(NR_FILE_PAGES) - total_swapcache_pages() - val->bufferram
"SwapCached:     %8lu kB\n" // total_swapcache_pages()
"Active:         %8lu kB\n" // global_page_state(NR_ACTIVE_ANON) +  global_page_state(NR_ACTIVE_FILE) 
"Inactive:       %8lu kB\n" // global_page_state(NR_INACTIVE_ANON) +  global_page_state(NR_INACTIVE_FILE)



Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자






 

[공유] 라즈비안 커널 빌드 스크립트 파일 Question_Announcement

'디버깅을 통해 배우는 리눅스 커널의 구조와 원리'의 저자 김동현입니다.

2장에서 라즈비안 커널 소스를 내려받고 빌드하는 과정에서 어려움을 겪고 있는 독자분들이 있는데요.
블로그에 댓글이나 이메일로 문제 현상을 알려주셨습니다.

그런데 대부분의 경우 빌드 스크립트를 입력하시다가 오타를 입력해 라즈비안 커널이 제대로 설치가 되지 않는 현상을 겪고 계신 것 같아요.

빌드 스크립트를 입력하는 도중에 오타를 입력하면 제대로 라즈비안 커널이 빌드가 되지 않아 불필요한 고생할 수 있습니다. 사실 2.3.3절에 소개된 build_rpi_kernel.sh와 install_rpi_kernel_img.sh 파일은 라즈비안 커널을 손쉽게 빌드하기 위해 작성된 빌드 스크립트이니, 일일이 명령어를 입력할 필요가 없습니다. 

따라서 다음 링크에 업로드된 파일을 내려받으신 후, build_rpi_kernel.sh와 install_rpi_kernel_img.sh 파일을 그대로 실행해 라즈비안 커널 이미지를 빌드하고 설치하시길 권장합니다.

라즈베리 파이 3B:


     * '디버깅을 통해 배우는 리눅스 커널의 구조와 원리'에 소개된 라즈비안 커널 빌드 스크립트
     * 라즈베리 파이 3B 기준


라즈베리 파이4:


    *라즈베리 파이 4B 기준 라즈비안 커널 빌드 스크립트

위 링크에 raspberry_pi_3B_kernel_build_script.zip 혹은 raspberry_pi_4_kernel_build_script.zip 파일을 클릭하면 빌드 스크립트 파일을 내려받을 수 있습니다.

마지막으로 이 책을 선택해주신 독자분께 감사의 말씀을 드리고 싶고요. 책을 읽다가 궁금한 점이 있으면 댓글로 질문 주시면 최대한 성실히 답변 드리겠습니다.

감사합니다.
김동현 드림.









[리눅스커널] 유튜브 동영상: TRACE32로 프로세스의 콜 스택 확인해보기(v.f /task 0xF1618000) 유튜브 동영상 강의자료

이번에는 TRACE32로 프로세스의 콜 스택을 보는 내용을 설명하는 강의 동영상입니다.




동영상 참고하셔서, 즐겁게 리눅스 커널을 디버깅하셨으면 좋겠네요.

[리눅스커널] 유튜브 동영상: TRACE32로 프로세스 스택 디버깅해보기 4. 프로세스(Process) 관리

책이나 블로그 포스트에 아무리 열심히 글을 써도 잘 설명이 되지 않는 내용이 있으면, 유튜브로 강의 동영상을 올리면 좋을 때가 있습니다. 

아래 콘텐츠는 TRACE32로 프로세스의 스택 공간을 디버깅하는 내용입니다.



동영상을 보고 프로세스의 스택에 대해 조금 더 잘 이해하셨으면 좋겠습니다.

[리눅스커널] Soft IRQ 서비스 요청 전체 흐름도 6. 인터럽트 후반부 처리

이번에 Soft IRQ 전체 흐름도를 보면서 Soft IRQ 서비스를 요청하는 시점에 대해서 확인해볼까요?

  
그림 6.11 Soft IRQ 서비스 요청 시 자료구조

위 그림 가장 왼쪽을 보면 '인터럽트 처리'라는 박스가 보입니다. 이는 인터럽트 핸들러나 인터럽트 핸들러 서브 루틴에서 호출하는 함수 동작을 의미합니다. 이 박스 아랫 부분을 눈으로 따라가보면 '__raise_softirq_irqoff' 가 보입니다. 이는 다음 동작을 하는 함수 이름입니다. 

    Soft IRQ 서비스를 요청한다. 

 

* 유튜브 강의 동영상도 있으니 같이 들으시면 좋습니다.




"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim

repository-[리눅스커널] Soft IRQ 서비스 요청 전체 흐름도
http://rousalome.egloos.com/10025114


[리눅스커널] Soft IRQ: 태스크릿 실행 요청은 어떻게 할까? 6. 인터럽트 후반부 처리

tasklet_init() 함수 호출로 태스크릿을 초기화했으면 태스크릿으로 등록한 핸들러 함수실행 요청을 해야 합니다. 이를 위해 tasklet_schedule() 함수를 호출해야 합니다.

태스크릿 전체 흐름도에서 태스크릿 실행 요청 확인하기

다음 태스크릿 전체 흐름도를 보면서 태스크릿 실행 요청 과정을 보겠습니다. 

 
 
#인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim


http://rousalome.egloos.com/10025227

[리눅스커널] Soft IRQ: 태스크릿의 전체 실행 흐름 파악 6. 인터럽트 후반부 처리

태스크릿 전체 실행 흐름은 다음 그림에서 확인할 수 있습니다.


 
[그림 6.18] 태스크릿 실행 단계 별 전체 흐름도

태스크릿은 Soft IRQ 서비스 중 하나이므로 이전 절에 배웠던 Soft IRQ 흐름도와 거의 비슷합니다. Soft IRQ 서비스 실행 흐름 과정을 떠올리면서 태스크릿 실행 과정을 보겠습니다.

[1] 단계
인터럽트 핸들러에서 tasklet_schedule() 함수를 호출해 태스크릿 스케줄링을 실행합니다. tasklet_schedule() 함수는 raise_softirq_irqoff() 함수를 호출해 TASKLET Soft IRQ 서비스를 요청합니다.

[2] 단계
Soft IRQ 서비스 핸들러를 호출하는 __do_softirq() 함수에서 태스크릿 서비스 핸들러인 tasklet_action() 함수를 호출합니다. tasklet_action() 함수에서 태스크릿 핸들러 함수를 호출합니다.

[3] 단계
Soft IRQ 서비스 핸들러 실행 후 실행 시간을 체크해 ksoftirqd 스레드를 깨우고 실행을 마무리합니다.

[4] 단계
ksoftirqd 스레드에서 태스크릿 서비스 핸들러인 tasklet_action() 함수를 호출합니다. tasklet_action() 함수에서 태스크릿 핸들러 함수를 호출합니다.

다음 소절에서 1단계인 태스크릿 실행 요청을 살펴보겠습니다.

#인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim

http://rousalome.egloos.com/10025226


[리눅스커널] Soft IRQ: 태스크릿 자료구조란 6. 인터럽트 후반부 처리

태스크릿을 표현하는 자료구조는 struct tasklet_struct이며 선언부는 다음과 같습니다.
 
https://elixir.bootlin.com/linux/v4.19.30/source/include/linux/interrupt.h 
01 struct tasklet_struct
02 {
03 struct tasklet_struct *next;
04 unsigned long state;
05 atomic_t count;
06 void (*func)(unsigned long);
07 unsigned long data;
08 };

struct tasklet_struct *next;
   태스크릿으로의 포인터입니다.
   
unsigned long state;
태스크릿 상태를 담고 있으며 태스크릿 세부 제어를 위해 씁니다.

state 필드는 다음에 선언된 플래그 중 하나를 저장합니다.
   
https://elixir.bootlin.com/linux/v4.19.30/source/include/linux/interrupt.h 
enum
{
TASKLET_STATE_SCHED, /* Tasklet is scheduled for execution */
TASKLET_STATE_RUN /* Tasklet is running (SMP only) */
};

TASKLET_STATE_SCHED는 태스크릿이 실행을 위해 스케줄링, TASKLET_STATE_RUN는 태스크릿이 실행 중인 상태입니다.

atomic_t count; 

태스크릿 레퍼런스 카운터이며 태스크릿을 초기화하는 tasklet_init() 함수에서 0으로 설정됩니다. count는 태스크릿 실행 여부를 판단하는 중요한 필드입니다. 반드시 0 이어야만 태스크릿을 실행합니다.

void (*func)(unsigned long);

태스크릿 핸들러 함수입니다.

tasklet_init() 함수를 호출할 때 2 번째 인자로 핸들러 함수를 등록합니다.

https://elixir.bootlin.com/linux/v4.19.30/source/include/linux/interrupt.h 
extern void tasklet_init(struct tasklet_struct *t,
 void (*func)(unsigned long), unsigned long data);

unsigned long data;
태스크릿 핸들러 함수에 전달되는 매개인자입니다.

* 강의 동영상도 있으니 같이 들으시면 좋습니다.





"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"

#인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim


http://rousalome.egloos.com/10025224


[리눅스커널] Soft IRQ 컨텍스트는 어떻게 확인할까? 6. 인터럽트 후반부 처리

현재 실행 중인 코드가 Soft IRQ 컨택스트인지를 알려면 in_softirq() 함수를 쓰면 됩니다.

in_softirq() 함수를 호출해 true를 반환하면 현재 실행 중인 코드가 Soft IRQ 컨택스트인 것입니다.
[https://elixir.bootlin.com/linux/v4.19.30/source/include/linux/preempt.h]
#define in_softirq() (softirq_count())

* 유튜브 강의 동영상도 있으니 같이 들으시면 좋습니다.



"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"

#인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim




[리눅스커널] Soft IRQ 컨텍스트는 언제 시작할까? 6. 인터럽트 후반부 처리

Soft IRQ 컨택스트를 활성화할 때 변경하는 자료구조는 무엇일까요?
각각 프로세스의 스택 최상단 주소에 있는 struct thread_info 구조체 preempt_count 필드입니다.

Soft IRQ 컨택스트일 때는 struct thread_info 구조체 preempt_count 필드가 0x100 으로 바꾸고 Soft IRQ 컨택스트가 아닐 때는 0x100을 Clear합니다.   

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim

http://rousalome.egloos.com/10025221

[리눅스커널] Soft IRQ: ksoftirqd 핸들러인 run_softirqd() 함수 분석 6. 인터럽트 후반부 처리

다음에 볼 코드는 ksoftirqd 프로세스가 실행될 때 호출되는 run_ksoftirqd() 함수입니다. 
 
* 유튜브 강의 동영상도 있으니 같이 들으시면 좋습니다.




"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
그리고 혹시 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려드리겠습니다!"

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim

http://rousalome.egloos.com/10025219



[리눅스커널] Soft IRQ: ksoftirqd 스레드는 언제 깨울까? 6. 인터럽트 후반부 처리

ksoftirqd 스레드는 깨우려면 wakeup_softirqd() 함수를 호출해야 합니다. 이 함수는 다음 조건에서 호출합니다.

  ❑ __do_softirq() 함수에서 Soft IRQ 서비스 실행 중 MAX_SOFTIRQ_TIME 지피 시간만큼 경과했을 때
  ❑ 인터럽트 컨택스트가 아닌 상황에서 Soft IRQ 서비스를 요청할 때

ksoftirqd 스레드를 깨우는 wakeup_softirqd() 함수를 분석하겠습니다. 


인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim



http://rousalome.egloos.com/10025218


[리눅스커널] Soft IRQ: ksoftirqd 스레드 깨우기 6. 인터럽트 후반부 처리

Soft IRQ 서비스 핸들러를 호출하는 __do_softirq() 함수 실행 시간이 길면 ksoftirqd 스레드를 깨웁니다.  

* 강의 동영상도 있으니 같이 들으시면 좋습니다.




"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  

# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2




http://rousalome.egloos.com/10025216

[리눅스커널] Soft IRQ 서비스 요청 점검 6. 인터럽트 후반부 처리

이전 소절에 분석한 바와 같이 인터럽트 핸들러 처리를 마무리 한 후 irq_exit() 함수를 호출합니다. irq_exit() 함수에서 Soft IRQ 서비스 요청을 점검하는 부분부터 분석하겠습니다. 

* 강의 동영상도 있으니 같이 들으시면 좋습니다.





"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  

# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2




http://rousalome.egloos.com/10025214



[리눅스커널] Soft IRQ 서비스를 요청했는지는 누가 어떻게 점검할까? 6. 인터럽트 후반부 처리

Soft IRQ 서비스를 요청하는 코드를 살펴봤습니다. Soft IRQ 서비스를 요청했으면 어디선가 이 서비스 요청 알아보고 점검할 것입니다. Soft IRQ 서비스를 요청했는지는 누가 어떻게 점검할까요? 

Soft IRQ 서비스 요청 여부는 인터럽트 핸들러 수행이 끝나면 호출하는 irq_exit()과 ksoftirqd 스레드 핸들 함수인 run_ksoftirqd() 함수에서 점검합니다. 이 때 커널에서 제공하는 local_softirq_pending() 함수를 호출합니다. 

* 유튜브 강의 동영상도 있으니 같이 들으시면 좋습니다.



"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


 
http://rousalome.egloos.com/10025212






[리눅스커널] Soft IRQ: irq_stat 전역변수 분석 6. 인터럽트 후반부 처리

or_softirq_pending() 함수를 호출하면 irq_stat 전역 변수에 비트 마스크를 설정합니다.
Soft IRQ 서비스를 요청하면 이 정보를 irq_stat란 전역 변수에 저장합니다. 

* 유튜브 강의 동영상도 있으니 같이 들으시면 좋습니다.




"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim


repository-[리눅스커널] Soft IRQ: irq_stat 전역변수 분석 
http://rousalome.egloos.com/10025119

[리눅스커널] Soft IRQ: raise_softirq() 함수 분석 6. 인터럽트 후반부 처리

Soft IRQ 서비스를 요청하려면 raise_softirq() 함수 혹은 __raise_softirq_irqoff() 함수를 호출해야 합니다. raise_softirq() 함수 분석으로 Soft IRQ 서비스 요청 세부 동작을 알아봅시다.

* 유튜브 강의 동영상도 있으니 같이 들으시면 좋습니다.




"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim


repository-[리눅스커널] Soft IRQ: raise_softirq() 함수 분석 
http://rousalome.egloos.com/10025118




[리눅스커널] Soft IRQ 서비스 핸들러의 등록 과정 실습 6. 인터럽트 후반부 처리

지금까지 Soft IRQ 서비스를 등록하려면 open_softirq() 함수를 호출해야 한다고 배웠습니다.
이어서 라즈베리파이에서 Soft IRQ 서비스 등록 과정을 실습으로 더 알아보겠습니다.  

* 유튜브 강의 동영상도 있으니 같이 들으시면 좋습니다.




"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim


repository-[리눅스커널] Soft IRQ 서비스 핸들러의 등록 과정 실습 
http://rousalome.egloos.com/10025116

[리눅스커널] Soft IRQ 서비스 핸들러는 언제 등록할까? 6. 인터럽트 후반부 처리

이전 소절에서 다룬 바와 같이 Soft IRQ 실행 1단계는 'Soft IRQ 서비스를 등록'입니다.
Soft IRQ 서비스는 부팅 과정에서 등록하며 이를 위해 open_softirq() 함수를 호출해야 합니다.

이제 open_softirq() 함수를 중심으로 Soft IRQ 서비스 등록 과정을 살펴보겠습니다. 

* 유튜브 강의 동영상도 있으니 같이 들으시면 좋습니다.




"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim


repository-[리눅스커널] Soft IRQ 서비스 핸들러는 언제 등록할까? 
http://rousalome.egloos.com/10025115


[리눅스커널] Soft IRQ는 왜 알아야 할까? 6. 인터럽트 후반부 처리

마지막으로 Soft IRQ를 왜 배워야 하는지 알아봅시다.

1. 리눅스 커널 입문자를 벗어나 중급 수준 개발자가 되려면 Soft IRQ가 뭔지 알아야 합니다. 반응 속도에 민감한 네트워크 패킷 처리나 고속 그래픽 처리 및 스토리지(UFS) 드라이버들은 Soft IRQ 핸들러를 이용해서 구현됐기 때문입니다.

2. 우리는 인터럽트가 발생하면 일하던 프로세스를 멈추고 인터럽트 핸들러를 실행한다고 알고 있습니다. 그런데 Soft IRQ는 인터럽트 핸들러가 수행하면 일하던 프로세스로 돌아가지 않고 바로 Soft IRQ 실행을 시작합니다. Soft IRQ 에서 실행 속도가 늦으면 시스템 반응 속도가 늦어질 수 있습니다. 시스템 성능 문제가 생겼을 때 체크해야 할 점검 포인트 중 하나입니다. 그래서 시스템 전반을 책임지는 개발자는 Soft IRQ를 잘 이해하고 있어야 합니다.

3. 커널 타이머를 제대로 이해하려면 Soft IRQ 구조를 알아야 합니다. 드라이버에서 요청한 로컬 타이머들은 타이머 인터럽트가 발생한 다음 Soft IRQ 서비스로 실행하기 때문입니다.

4. 태스크릿은 Soft IRQ 서비스 형태로 사용합니다. 태스크릿을 제대로 이해하려면 Soft IRQ를 알아야 합니다.

* 유튜브 강의 동영상도 있으니 같이 들으시면 좋습니다.




"이 포스팅이 유익하다고 생각되시면 댓글로 응원해주시면 감사하겠습니다.  
혹시 글을 읽고 궁금점이 있으면 댓글로 질문 남겨주세요. 상세한 답글 올려 드리겠습니다!"

인터럽트 후반부(IRQ 스레드/Soft IRQ) 처리

인터럽트 후반부 기법이란?  
IRQ 스레드(threaded IRQ)  
   * IRQ란?   
IRQ 스레드는 어떻게 생성할까?  
IRQ 스레드는 누가 언제 실행할까?  
IRQ 스레드 디버깅 실습  
Soft IRQ 소개  
Soft IRQ 서비스  
Soft IRQ 서비스는 언제 요청할까?  
Soft IRQ 서비스는 누가 언제 처리할까?  
ksoftirqd 스레드  
Soft IRQ 컨텍스트에 대해  
태스크릿  
Soft IRQ 디버깅  


# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


Thanks,
Austin Kim

repository-[리눅스커널] Soft IRQ는 왜 알아야 할까?
http://rousalome.egloos.com/10025113


1 2 3 4 5 6 7 8 9 10 다음