Embedded Linux: Character Device Driver 작성
Embedded Linux에서 Character Device Driver는 장치와 사용자 공간 간의 데이터 교환을 처리하는 중요한 구성 요소입니다. 이번 포스팅에서는 Character Device Driver가 무엇인지 알아보고, Rockchip RK3399 시스템에서 간단한 Char Driver를 작성하고 테스트하는 방법을 설명하겠습니다.
Character Device Driver란 무엇인가?
Character Device Driver(문자 장치 드라이버)는 바이트 단위로 데이터를 처리하는 드라이버로, 키보드, 시리얼 포트, 터미널 등과 같은 장치를 제어하는 데 사용됩니다.
특징:
- 순차적으로 데이터를 읽고 쓸 수 있습니다.
- 파일 인터페이스를 통해 사용자 공간과 커널 공간 간의 데이터 교환을 제공합니다.
/dev
디렉토리 아래에 파일로 나타납니다.
주요 인터페이스:
open
,read
,write
,close
와 같은 파일 연산자(file operations)를 구현해야 합니다.
간단한 Char Driver 작성 및 테스트
다음은 Rockchip RK3399에서 간단한 Character Device Driver를 작성하고 테스트하는 단계입니다.
1. 커널 모듈 작성
아래는 간단한 Char Driver의 소스 코드입니다. 이 드라이버는 사용자로부터 문자열을 쓰고, 다시 읽어오는 기본적인 동작을 수행합니다.
// simple_char_driver.c
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/cdev.h>
#define DEVICE_NAME "simple_char"
#define BUFFER_SIZE 1024
static int major;
static char buffer[BUFFER_SIZE];
static struct cdev simple_cdev;
// open 함수
static int simple_open(struct inode *inode, struct file *file) {
pr_info("simple_char: Device opened\n");
return 0;
}
// close 함수
static int simple_close(struct inode *inode, struct file *file) {
pr_info("simple_char: Device closed\n");
return 0;
}
// read 함수
static ssize_t simple_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) {
size_t len = strlen(buffer);
if (*ppos >= len) return 0; // EOF
if (count + *ppos > len) count = len - *ppos;
if (copy_to_user(user_buf, buffer + *ppos, count)) return -EFAULT;
*ppos += count;
pr_info("simple_char: Read %zu bytes\n", count);
return count;
}
// write 함수
static ssize_t simple_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) {
if (count > BUFFER_SIZE - 1) return -EINVAL;
memset(buffer, 0, BUFFER_SIZE);
if (copy_from_user(buffer, user_buf, count)) return -EFAULT;
pr_info("simple_char: Received %zu bytes\n", count);
return count;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = simple_open,
.release = simple_close,
.read = simple_read,
.write = simple_write,
};
static int __init simple_init(void) {
dev_t dev;
int ret;
ret = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
if (ret < 0) {
pr_err("simple_char: Failed to allocate device number\n");
return ret;
}
major = MAJOR(dev);
cdev_init(&simple_cdev, &fops);
ret = cdev_add(&simple_cdev, dev, 1);
if (ret < 0) {
unregister_chrdev_region(dev, 1);
pr_err("simple_char: Failed to add cdev\n");
return ret;
}
pr_info("simple_char: Registered with major %d\n", major);
return 0;
}
static void __exit simple_exit(void) {
cdev_del(&simple_cdev);
unregister_chrdev_region(MKDEV(major, 0), 1);
pr_info("simple_char: Unregistered device\n");
}
module_init(simple_init);
module_exit(simple_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple character device driver");
2. 모듈 컴파일
위 코드를 simple_char_driver.c
로 저장한 뒤, 다음과 같은 Makefile
을 작성합니다.
obj-m += simple_char_driver.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
컴파일 명령:
make
3. 모듈 삽입 및 테스트
모듈 삽입:
sudo insmod simple_char_driver.ko
디바이스 파일 생성:
sudo mknod /dev/simple_char c <major_number> 0 sudo chmod 666 /dev/simple_char
위에서
<major_number>
는 모듈 로드 시 출력된 메이저 번호로 교체합니다.테스트:
데이터 쓰기:
echo "Hello, RK3399!" > /dev/simple_char
데이터 읽기:
cat /dev/simple_char
모듈 제거:
sudo rmmod simple_char_driver sudo rm /dev/simple_char
결론
이번 포스팅에서는 Character Device Driver의 기본 개념과 Rockchip RK3399에서 간단한 Char Driver를 작성하고 테스트하는 방법을 살펴보았습니다. 이를 기반으로 더 복잡한 드라이버를 설계하거나 다양한 기능을 추가해볼 수 있습니다.
'Linux > Kernel Driver' 카테고리의 다른 글
Embedded Linux Kernel: Platform Driver 작성하기 (0) | 2025.03.19 |
---|---|
Device Driver에서 Sysfs 등록 (0) | 2025.03.18 |
Linux Kernel 모듈 기본 (0) | 2025.03.16 |
Embedded Linux에서 Root Filesystem 생성하기 (0) | 2025.03.15 |
Embedded Linux Kernel 설정 - Kernel Configuration (0) | 2025.03.14 |