본문 바로가기

Core BSP 분석/리눅스 커널 핵심 분석

(90)
[리눅스커널][디버깅] 슬럽(슬랩) 캐시 오브젝트 T32로 메모리 디버깅하기 리눅스 커널 동적 메모리 할당을 위해 슬럽 캐시를 씁니다. 이번 시간에서는 kmalloc-64 슬럽 캐시 자료 구조를 통해 kmalloc-64 슬럽 오브젝트를 확인하는 방법을 소개합니다. 슬럽 캐시 확인하기 먼저 kmalloc-size 타입 슬럽 캐시를 관리하는 kmalloc_caches 전역 변수를 보겠습니다. kmalloc_caches 전역 변수의 세부 필드는 다음과 같습니다. (static struct kmem_cache * [14]) kmalloc_caches = ( [0] = 0x0, [1] = 0x0, [2] = 0xF1401E00, // "kmalloc-192" [3] = 0x0, [4] = 0x0, [5] = 0x0, [6] = 0xF1401F00 -> ( (struct kmem_cache..
[리눅스커널][디버깅] 유저공간 High Memory Zone 페이지 할당 과정 커널 크래시가 발생한 콜스택은 다음과 같습니다. 프로세스는 이름은 Debugger인데 유저 프로세스입니다. -001|__dabt_svc(asm) -->|exception -002|__list_del(inline) -002|list_del(inline) -002|buffered_rmqueue(inline) -002|get_page_from_freelist(?, ?, order = 0, ?, high_zoneidx = 0, alloc_flags = 449, pref -003|__alloc_pages_nodemask(gfp_mask = 33685722, order = 0, zonelist = 0xC1731380, nodema -004|__alloc_zeroed_user_highpage(inline) -004|..
[Linux][Kernel] preempt_disable()/preempt_enable() 주의 사항 preempt_disable() 함수를 쓸 때 주의해야 할 점이 있습니다. preempt_disable() 함수는 preempt_enable() 함수와 반드시 Pair로 써야 합니다. preempt_disable() 함수를 호출한 다음 스케줄링 동작을 수행하는 함수를 쓰면 리눅스 시스템은 오동작합니다. 예를 들어 다음과 같은 드라이버를 초기화하는 코드를 예를 들겠습니다. 1 void configure_something_driver(void) 2 { 3 preempt_disable(); 4 5 do_something(); 6 mdelay(100); 7 do_something(); 8 9 preempt_enable(); 10 } 5~7 번 코드가 실행할 때 Preemption이 되면 안된다고 판단했습니다. ..
[라즈베리파이] 비트 처리 __test_and_set_bit() __test_and_clear_bit() 함수 동작 원리 리눅스 커널과 드라이버에서 __test_and_set_bit()와 __test_and_clear_bit() 함수를 많이 씁니다. 두 함수 중 test_and_set_bit()를 써서 비트를 처리하는 코드를 보겠습니다. 다음은 워크를 워크큐에 큐잉하는 queue_work_on() 함수입니다. [kernel/workqueue.c] 1 bool queue_work_on(int cpu, struct workqueue_struct *wq, 2 struct work_struct *work) 3 { 4 bool ret = false; 5 unsigned long flags; 6 7 local_irq_save(flags); 8 9 if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, wo..
[리눅스] printk 아규먼트 포멧 printk에 %로 어떤 형식을 지정할 지 헷갈릴 때가 많습니다. 이럴 때는 다음 형식을 참고하면 됩니다. If variable is of Type, use printk format specifier: ------------------------------------------------------------ int %d or %x unsigned int %u or %x long %ld or %lx unsigned long %lu or %lx long long %lld or %llx unsigned long long %llu or %llx size_t %zu or %zx ssize_t %zd or %zx s32 %d or %x u32 %u or %x s64 %lld or %llx u64 %llu or %..
[C언어] 포인터 (p + 1) 연산 포인터의 기본 문법에 대해서 조금 더 알아볼게요. 코드는 다음과 같습니다. int i = 10; int *p = &i; *p = 20; 이 때 64 비트 CPU 기반으로 메모리 구조를 한번 그려볼까요? 1008번지에는 i란 지역변수가 있고 1000 번지에는 p란 포인터 타입 지역 변수가 위치해 있죠. 포인터 주소 값 | 1000 |--- 1008 | | p | 1008 |--- (10 -> 20) i 변수 i의 위치가 1008번지라면 포인터 변수 p에는 i 변수 주소를 대입했으므로 p는 int을 가르키는 주소가 됩니다. 이 때 주소 변수를 선언하는 방법은 int *p입니다. 그런데 컴파일러는 이 선언부를 다음과 같이 해석합니다. pointer to int 주소 변수를 가르키는 대상체의 타입이 중요하므로 ..
[Linux][GCC]## 매크로 - 심볼 생성 리눅스 커널 코드를 읽다 보면 C 코드에는 존재하지 않는 함수를 호출하는 경우가 있습니다. 희한하게도 해당 함수를 아무리 검색해도 찾을 수 없는데 다른 함수에서 아무 문제 없이 호출합니다. 자 그럼 한 가지 예를 들게요. 아래 코드를 보면 end_page_writeback 함수에서 PageReclaim와 ClearPageReclaim 함수를 호출합니다. 이 함수는 페이지 write back 동작을 멈추는 역할을 하는 것으로 보이네요. [mm/filemap.c] void end_page_writeback(struct page *page) { if (PageReclaim(page)) { ClearPageReclaim(page); rotate_reclaimable_page(page); } PageReclaim..
[Linux] 컴파일러(Complier) 소개 소프트웨어에 입문하는 분들은 컴파일러란 단어를 매우 자주 들을 가능성이 높습니다. 왜냐면 현업에서 가장 많이 쓰는 단어 중 하나이거든요. 그럼 컴파일이란 단어를 영한 사전으로 찾으면 "안내서를 만들다.", "책을 편집하다."란 의미입니다. 그러면 "컴퓨터에게 편집해서 안내서를 만든다"란 문장으로 컴파일이란 단어를 조합할 수 있는 것 같습니다. x86, ARM과 같은 CPU가 해석할 수 있는 것은 오로지 명령어이며, 이는 비트 패턴인 기계어를 뜻합니다. "프로세스는 이미 정해진 특정한 비트 패턴에 반응한다"란 의미로 특정 비트 패턴을 명령어라고 부를 수 있습니다. 조금 쉽게 설명을 드리면 CPU는 여러가지 전기적 스위치로 구성돼 있으며, 어떤 특정한 전기 스위치를 작동시키려면 데이터 버스 선을 따라 전압이..