리눅스는 모놀리식 커널이지만, 커널 모듈 덕분에 런타임에 기능을 추가/제거할 수 있습니다. USB 드라이버를 꽂으면 자동으로 로드되는 것이 이 메커니즘입니다.


커널 모듈이란

LKM(Loadable Kernel Module) 은 커널을 재부팅하지 않고 런타임에 로드/언로드할 수 있는 코드 조각입니다.

PLAINTEXT
리눅스 커널
┌─────────────────────────────┐
│  핵심 커널 (항상 메모리에)      │
│  ┌────┬──────┬────────────┐│
│  │스케줄│메모리 │파일 시스템   ││
│  │러   │관리  │(기본)      ││
│  └────┴──────┴────────────┘│
│                             │
│  커널 모듈 (필요할 때 로드)     │
│  ┌────┐ ┌─────┐ ┌────────┐│
│  │USB │ │NIC  │ │파일시스템││
│  │드라이│ │드라이│ │(ext4)  ││
│  │버   │ │버   │ │        ││
│  └────┘ └─────┘ └────────┘│
└─────────────────────────────┘

간단한 커널 모듈 작성

C
// hello.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("developer");
MODULE_DESCRIPTION("Hello World 커널 모듈");

// 모듈 로드 시 호출
static int __init hello_init(void) {
    printk(KERN_INFO "Hello, Kernel Module!\n");
    return 0;  // 0: 성공, 음수: 에러
}

// 모듈 언로드 시 호출
static void __exit hello_exit(void) {
    printk(KERN_INFO "Goodbye, Kernel Module!\n");
}

module_init(hello_init);
module_exit(hello_exit);

Makefile

MAKEFILE
obj-m += hello.o

all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

모듈 관리 명령어

BASH
# 모듈 빌드
make

# 모듈 로드
sudo insmod hello.ko

# 모듈 확인
lsmod | grep hello

# 커널 로그 확인
dmesg | tail

# 모듈 언로드
sudo rmmod hello

# 의존성까지 자동 로드
sudo modprobe hello

# 모듈 정보 확인
modinfo hello.ko

디바이스 드라이버

리눅스에서 디바이스는 파일 로 추상화됩니다 (/dev/ 하위).

디바이스 유형

유형설명예시
문자 디바이스바이트 스트림/dev/tty, /dev/null
블록 디바이스블록 단위 I/O/dev/sda, /dev/nvme0n1
네트워크 디바이스네트워크 인터페이스eth0, wlan0

문자 디바이스 드라이버 구조

C
#include <linux/fs.h>
#include <linux/cdev.h>

// 파일 연산 구조체
static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = device_open,      // open() 시스템 콜 처리
    .release = device_release, // close() 처리
    .read = device_read,      // read() 처리
    .write = device_write,    // write() 처리
};

static int device_open(struct inode *inode, struct file *file) {
    printk(KERN_INFO "디바이스가 열렸습니다\n");
    return 0;
}

static ssize_t device_read(struct file *file, char __user *buf,
                           size_t count, loff_t *offset) {
    // 커널 → 유저 공간으로 데이터 복사
    copy_to_user(buf, kernel_buffer, count);
    return count;
}

모듈 매개변수

C
static int count = 1;
static char *name = "default";

module_param(count, int, 0644);    // /sys/module/xxx/parameters/count
module_param(name, charp, 0644);

MODULE_PARM_DESC(count, "반복 횟수");
MODULE_PARM_DESC(name, "모듈 이름");
BASH
# 매개변수 전달
sudo insmod hello.ko count=5 name="test"

핵심 포인트

  • 커널 모듈 vs 마이크로커널: 모듈은 커널 공간에서 실행되므로 버그 시 커널 크래시 가능 — 진정한 격리가 아님
  • insmod vs modprobe: modprobe는 의존성을 자동 해결, insmod은 수동
  • printk vs printf: 커널에서는 printf 사용 불가 — printk로 커널 링 버퍼에 출력

정리

커널 모듈은 리눅스가 모놀리식 커널이면서도 유연성을 유지할 수 있게 해주는 핵심 메커니즘입니다. 드라이버 개발의 기본이기도 하며, 커널과 유저 공간의 경계를 이해하는 데 중요한 개념입니다.

댓글 로딩 중...