Character Device Driver 실습
Source Code & Makefile 작성
- 작업 디렉터리 생성(위치는 아무곳이나 상관 없음)
$ mkdir driver
$ cd driver
$ mkdir chardev
- Source Code 작성
- 생성한 chardev 디렉터리 밑에 생성(chardev.c)
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#define CHR_DEV_NAME "chardev"
#define CHR_DEV_MAJOR 255
int chr_open(struct inode * inode, struct file * file)
{
int number = MINOR(inode->i_rdev);
printk("Virtual Character Device Open : Minor Number is %d\n", number);
return 0;
}
ssize_t chr_write(struct file * file, const char * buf, size_t count, loff_t * f_pos)
{
printk("write data : %s\n", buf);
return count;
}
ssize_t chr_read(struct file * filep, char * buf, size_t count, loff_t * f_pos)
{
printk("read data : %s\n", buf);
return count;
}
long chr_ioctl(struct file * filep, unsigned int cmd, unsigned long arg)
{
switch(cmd) {
case 0: printk("cmd value is %d\n", cmd); break;
case 1: printk("cmd value is %d\n", cmd); break;
case 2: printk("cmd value is %d\n", cmd); break;
case 3: printk("cmd value is %d\n", cmd); break;
case 4: printk("cmd value is %d\n", cmd); break;
}
return 0;
}
int chr_release(struct inode * inode, struct file * filep)
{
printk("Virtual Character Device Release\n");
return 0;
}
struct file_operations chr_fops =
{
.owner = THIS_MODULE,
.write = chr_write,
.read = chr_read,
.open = chr_open,
.release = chr_release,
.unlocked_ioctl = chr_ioctl,
};
int chr_init(void)
{
int registration;
printk("Registration Character Device to Kernel\n");
registration = register_chrdev(CHR_DEV_MAJOR, CHR_DEV_NAME, &chr_fops);
if (registration < 0)
return registration;
printk("Major Number : %d\n", registration);
return 0;
}
void chr_exit(void)
{
printk("Unregistration Character Device to Kernel\n");
unregister_chrdev(CHR_DEV_MAJOR, CHR_DEV_NAME);
}
module_init(chr_init);
module_exit(chr_exit);
MODULE_LICENSE("GPL");
- Makefile 작성
- 생성한 chardev 디렉터리 밑에 생성(Makefile)
obj-m += chardev.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all :
make -C $(KDIR) M=$(PWD) modules
clean :
rm -rf chardev.o chardev.mod.* chardev.ko
빌드 및 결과 확인
$ cd driver/chardev
$ make
$ ls
$ mkmod /dev/chardev c 255 0 // 코드에 명시한 내용과 똑같이 주번호 255, 부번호 0
$ insmod chardev.ko
$ lsmod | head -n 5
$ dmsg | tail -n 5
$ rmmod chardev
$ dmesg | tail -n 5
디바이스 드라이버 테스트
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#define DEVICE_FILE_NAME "/dev/chardev"
int main(int argc, char *argv[])
{
int device;
char wbuf[128] = "Write buffer data";
char rbuf[128] = "Read buffer data";
int n = atoi(argv[1]);
device = open(DEVICE_FILE_NAME, O_RDWR|O_NDELAY);
if (device >= 0)
{
printf("Device file Open\n");
ioctl(device, n);
write(device, wbuf, 10);
printf("Write value is %s\n", wbuf);
read(device, rbuf, 10);
printf("Read value is %s\n", rbuf);
} else {
perror("Device file open fail");
}
close(device);
return 0;
}
$ gcc -o chardev_test chardev_test.c
$ ./chardev_test 1
$ dmesg | tail -n 5