-
디바이스 드라이버 / 주 번호에 의한 파일 처리Linux/Linux Device Driver 2020. 9. 1. 12:41
주 번호에 의한 파일 처리는 register_chrdev()와 register_chrdev_region() 두 가지 함수를 사용할 수 있습니다.
pi@raspberrypi:~/Documents/major $ nano major_driver.c
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> // file_operations #include <linux/uaccess.h> // copy_to_user() #include <linux/slab.h> // kmalloc() #define MAJOR_DEV_NAME "major_dev" #define MAJOR_DEV_NUM 200 static int major_open(struct inode *inode, struct file *file) { printk("major_open\n"); return 0; } static ssize_t major_close(struct inode *inode, struct file *file) { printk("major_close\n"); return 0; } static ssize_t major_read(struct file *file, char *buf, size_t count, loff_t *f_pos) { int err; char *buff; buff = kmalloc(count, GFP_KERNEL); if(buff == NULL) { printk("malloc error\n"); return 0; } sprintf(buff, "KERNEL DATA"); err = copy_to_user(buf, buff, count); if(err != 0) { printk("copy_to_user error\n"); kfree(buff); return err; } printk("major_read -> count: %d, f_pos: %lld\n", count, *f_pos); kfree(buff); return 0; } static ssize_t major_write(struct file *file, const char *buf, size_t count, loff_t *f_pos) { char *buff; int err; buff = kmalloc(count, GFP_KERNEL); if(buff == NULL) { printk("kmalloc error\n"); return 0; } err = copy_from_user(buff, buf, count); if(err != 0) { printk("copy_from_user error\n"); kfree(buff); return err; } printk("major_write -> buff: %s, count: %d, f_pos: %lld\n", buff, count, *f_pos); kfree(buff); return 0; } struct file_operations major_fops = { .owner = THIS_MODULE, .open = major_open, .release = major_close, .read = major_read, .write = major_write, }; int major_init(void) { int err; printk("major_init\n"); err = register_chrdev(MAJOR_DEV_NUM, MAJOR_DEV_NAME, &major_fops); if(err < 0) { printk("register_chrdev error\n"); return err; } return 0; } void major_exit(void) { printk("major_exit\n"); unregister_chrdev(MAJOR_DEV_NUM, MAJOR_DEV_NAME); } module_init(major_init); module_exit(major_exit); MODULE_AUTHOR("icjk1003@gmail.com"); MODULE_LICENSE("GPL");
pi@raspberrypi:~/Documents/major $ nano major_app.c
#include <stdio.h> #include <fcntl.h> // open() #include <unistd.h> // write() read().. #include <stdlib.h> // exit() #include <string.h> // strlen() #define MAJOR_DEV_FILE_NAME "/dev/major_dev" char *msg = "USER DATA"; int main(int argc, char** argv) { int fd; char buf[1024]; fd = open(MAJOR_DEV_FILE_NAME, O_RDWR); if(fd < 0) { printf(MAJOR_DEV_FILE_NAME " open error\n"); exit(1); } read(fd, buf, 20); printf("read data: %s\n", buf); write(fd, msg, strlen(msg)+1); close(fd); return 0; }
pi@raspberrypi:~/Documents/major $ nano Makefile
obj-m := major_driver.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: major_app major_driver major_app: gcc -o $@ major_app.c major_driver: make -C $(KDIR) M=$(PWD) modules clean: make -C $(KDIR) M=$(PWD) clean rm major_app
pi@raspberrypi:~/Documents/major $ sudo make
pi@raspberrypi:~/Documents/major $ sudo insmod major_driver.ko
pi@raspberrypi:~/Documents/major $ sudo mknod /dev/major_dev 200 0
pi@raspberrypi:~/Documents/major $ sudo ./major_app
pi@raspberrypi:~/Documents/major $ dmesg
pi@raspberrypi:~/Documents/major $ sudo rmmod major_driver.ko
pi@raspberrypi:~/Documents/major $ sudo make clean
KERNEL DATA는 유저 영역에서 볼 수 있고 USER DATA는 커널 영역에서 볼 수 있다.
성공...
xxx_write() 함수에서는 const char * 매개변수가 가리키는 값을 그대로 읽을 수는 있지만 가리키는 값을 커널 영역으로 복사하지는 못한다. 그래서 copy_from_user() 함수를 사용하여 커널 영역으로 복사해야 한다.
xxx_write() 함수에서는 문자열 포인터를 사용할 경우 kmalloc() 함수로 동적 메모리 할당을 해야 한다.
틀린 점이 있다면 댓글 부탁드리겠습니다. 감사합니다.
'Linux > Linux Device Driver' 카테고리의 다른 글
디바이스 드라이버 / LED 제어 (0) 2020.09.01 디바이스 드라이버 / 부 번호에 의한 파일 처리 (0) 2020.09.01 디바이스 드라이버 / 메모리 풀 (0) 2020.09.01 디바이스 드라이버 / 동적 메모리 할당 (0) 2020.09.01 디바이스 드라이버 / 매개변수 지정 (0) 2020.09.01