임베디드를 좋아하는 조금 특이한 개발자?

[Linux Kernel Module] Character Device(문자 장치) 초기화 및 생성 본문

Embedded/Linux

[Linux Kernel Module] Character Device(문자 장치) 초기화 및 생성

Gordon_ 2025. 8. 11. 07:43

- 개발 환경

개발 보드 : Raspberrypi 4

OS : Linux raspberrypi 6.12.25


1. 서론

  먼저 리눅스에서는 Device(장치)또한 파일로 취급하여 관리하고 있습니다. 실제 /dev 폴더를 확인해보면 PC에 연결된 장치들을 확인 할 수 있습니다. 그리고 장치에 접근 방법에 따라 그리고 Character Device(이하 문자 장치)와 Block Device(이하 블록 장치)로 구분할 수 있습니다. 그 중 이번 포스트에서는 일반적으로 많이 사용되는 문자 장치을 초기화 및 생성하는 방법에 대해서 확인해보도록 하겠습니다

 

2. 관련 함수 및 구조체 확인

2.1. register_chrdev() 함수

int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)

https://elixir.bootlin.com/linux/v6.12.34/source/include/linux/fs.h#L2822

매개변수 확인)

- unsigned int major

  생성하고자 하는 문자 장치에 할당하고자 하는 major 번호를 설정합니다. 자동으로 할당하고자 할 때 0으로 설정합니다.

-  const char *name

  생성하고자 하는 문자 장치의 이름을 설정합니다.

- const struct file_operations *fops

  문자 장치에 접근하는 방법을 설정합니다.

 

반환 값)

  실제 할당한 major 번호를 반환합니다.

  만약, 에러가 발생한 음수를 반환합니다.

 

2.1. unregister_chrdev() 함수

static inline void unregister_chrdev(unsigned int major, const char *name)

https://elixir.bootlin.com/linux/v6.12.34/source/include/linux/fs.h#L2828

매개변수 확인)

- unsigned int major

  반납하고자 하는 문자 장치의 major의 번호를 전달합니다.

-  const char *name

  반납하고자 하는 문자 장치의 이름을 설정합니다.

 

2.3. struct file_operations 구조체

struct file_operations

 

https://elixir.bootlin.com/linux/v6.12.34/source/include/linux/fs.h#L2062

 

파일에 접근하기 위한 Callback 함수를 설정하기 위한 구조체입니다. 해당 구조체는 다른 포스트에서 자세히 다루도록 하겠습니다.

 

 

3. 모듈 프로그래밍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
 
// 문자 장치의 이름
#define CHAR_DEV_NAME               ("testDevice")
 
// 생성한 문자 장치의 Major 번호
static int major;
// 생성한 문자 장치을 제어하기 위한 함수를 관리하는 구조체
static struct file_operations fops ={
    .owner = THIS_MODULE,
};
 
static int __init initModule(void){
    // 문자 장치 생성
    major = register_chrdev(0, CHAR_DEV_NAME, &fops);
    // 문자 장치 생성시 에러가 발생한 경우
    if(major < 0){
        printk("[testDevice] Error : register_chrdev()\n");
        // 에러 반환
        return major;
    }
 
    // 정상적으로 문자 장치 생성됨을 알림 및 major 번호 확인
    printk("[testDevice] Success to init char device module\n");
    printk("[testDevice] Major : %d\n",major);
 
    return 0;
}
 
static void __exit exitModule(void){
 
    // 생성된 문자 장치를 해제
    unregister_chrdev(major, CHAR_DEV_NAME);
 
    printk("[testDevice] Error : exit module\n");
}
 
module_init(initModule);
module_exit(exitModule);
 
MODULE_LICENSE("GPL");
cs

 

4. 문자 장치와 노드 연결

# 모듈 빌드
make

# 모듈 등록
sudo insmod testDevice

 

 

dmesg를 통해 문자 장치가 정상적으로 생성됐음을 확인하였습니다. 또한 major 번호가 236임을 확인하였습니다. 이제 해당 문자 장치에 접근 하기 위한 파일을 생성하기 위해 노드를 연결하도록 하겠습니다.

 

# major 번호가 236, minor 번호가 0인 문자장치에 연결하기 위한 /dev/testDevice 노드를 생성
sudo mknod /dev/testDevice c 236 0

 

 

5. 후기

  문자 장치를 생성하고 노드를 연결하여 /dev 폴더 내 노드 파일을 생성하는 것 까지 완료 하였습니다. 하지만, 지금 상태로는 아무 것도 할 수 없습니다. fops를 통해 해당 문자 장치을 접근 하기 위한 함수를 등록하지 않았기 때문입니다. 다음 포스트에서는 fops에 함수를 등록하여 문자 장치에 접근 할 수 있는 방법을 알아보도록 하겠습니다.

문자 장치에 대한 접근 거부