Linux

커널 모듈 (insmod, lsmod, rmmod) 커널 API

Jminu 2025. 7. 30. 15:46

로드 가능한 커널 모듈 (Loadable Kernel Module)

  • 커널 이미지에 포함X -> 부팅시간, 메모리 절약
  • 커널에 덧 붙여서 커널의 기능 확장
  • 커널 주소 공간에서 실행
  1. linux/drivers/ 로 이동
  2. comento dir생성
  3. linux/drivers/comento에서 Kconfig, Makefile 생성

<linux/drivers/comento/Kconfig> 설정

menu "Comento Example Driver" # 메뉴 이름 설정

config COMENTO_EXAMPLE
	tristate "Comento Example Driver Module" # 3가지 옵션, y m n 사용가능
    help
    	This is an Example
 
endmenu # 메뉴 그룹 종료
  • 드라이버 모듈 설정 옵션을 정의

 

<linux/drivers/comento/Makefile> 설정

obj-$(CONFIG_COMENTO_EXAMPLE) += comento.o
comento-objs += main.o
  • CONFIG_COMENTO_EXAMPLE은 m으로 설정
  • obj-m += comento.o로 확장
    • comento.o는 모듈로 빌드 -> comento.ko 생성

<linux/drivers/Kconfig> 설정

...
...

source "drivers/comento/Kconfig"

마지막 부분에 추가

  • 파일의 내용을 현재 위치에 포함

<linux/drivers/Makefile> 설정

...
...

obj-y += comento/

마지막 부분에 추가

  • 해당 디렉토리/하위디렉토리를 전부 포함해서 빌드 대상으로 추가

커널에 새로운 모듈 추가

<linux/drivers/comento/main.c> 작성

#include <linux/module.h>

static int __init comento_module_init(void)
{
	printk(KERN_DEBUG "module [%s] init \n", __func__);
    return 0;
}

static void __exit comento_module_exit(void)
{
	printk(KERN_DEBUG "module [%s] exit \n", __func__);
}

module_init(comento_module_init);
module_exit(comento_module_exit);

MODULE_AUTHOR("Jin Minu");
MODULE_DESCRIPTION("Example Drvier");
MODULE_LICENSE("GPL v2");

코드 작성 후,

  1. 커널 재 빌드
  2. rootfs를 임시로 mnt디렉토리에 마운트
  3. 완성된 모듈 .ko 파일을 mnt/usr/lib/modules/ 에 복사
  4. sync
  5. umount 실행
  6. QEMU 실행
  7. insmod, lsmod, rmmod 로 모듈 로드/언로드
  8. dmesg로 확인

Kernel API

  • 메모리 관련
  • 더블 링크드 리스트
  • 해시테이블
  • 뮤텍스
  • 스핀락

1. 메모리 관련

  • copy_from_user(to, from, size) : 사용자 공간 -> 커널 공간으로 메모리 복사
  • copy_to_user(to from, size) : 커널 공간 -> 사용자 공간 메모리 복사
  • kmalloc(size, type) / kzalloc(size, type) : 커널 공간에서 메모리 동적 할당
    • type: GFP_KERNEL, GFP_ATOMIC, GFP_DMA

2. Doubly Linked List

  • linux/list.h에 정의
  • list_head 구조체 사용

API

  • LIST_HEAD(name)
  • list_add(new, head) / list_add_tail(new, head)
  • list_del(target)
  • list_empty(head)
  • list_for_each_safe(node, temp, head, member_name)

3. Hash Table

API

  • DEFINE_HASHTABLE(name)
  • hash_add(table, new, key)
  • hash_del(target)
  • hash_for_each_possible(table, node, member, key)
  • hash_for_each(table, bkt, node, hash)

4. Mutex

  • 동시에 접근하면 안되는 부분 지정 -> 하나의 변수를 동시에 수정한다면 문제 발생
  • 접근해서 작업이 오래걸릴 것을 예상 -> 컨텍스트 스위칭 발생
  • 바로바로 작업이 끝나고, 제어권 변경?? -> 스핀락 유리

API

  • DEFINE_MUTEX(name)
  • mutex_locK(mutex)
  • mutex_unlock(mutex)

5. Spinlock

  • 뮤텍스와 비슷, But 무한루프 사용해서 상태 바뀔 때까지 대기 -> 컨텍스트 스위칭 안함
  • Read-Write lock 형태 많이 사용
    • 데이터 read할 땐 여러 프로세스 허용
    • 데이터 write할 땐 하나의 프로세스만 허용
      • 쓸 때 읽는 것도 허용X

API

  • DEFINE_RWLOCK(name)
  • read_lock(mutex) / write_lock
  • read_unlock(mutex) / write_unlock

6. Current task

  • current: 현재 프로세스 참조, 전역변수, 커널 아무대서나 사용
  • aarch64에서는 특정 레지스터에 주소 보관
  • macro, inline함수