반응형
유저 커널 영역
Kernel Module Command and API
- insmod
- rmmod
- lsmod
- mknod
- modinfo
- depmod
- modprobe
- module_init()
- module_exit()
module_init 관련
- int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops)
- int register_blkdev(unsigned int, const char *)
- int register_netdev(struct net_device *dev
module_exit 관련
- void unregister_chrdev(unsigned int major, const char *name)
- int unregister_filesystem(struct file_system_type *)
- void unregister_netdev(struct net_device *dev)
process access 관련
- copy_to_user()
- copy_from_user()
copy_to_user 함수는 kernel space 에 있는 buffer 를 user space 의 buffer 로 copy 한다.
copy_form_user 함수는 user space 에 있는 buffer 를 kernel space 의 buffer 로 copy 한다.
static struct file_operations dohyeonmd_fops =
{
.owner=THIS_MODULE,
.open= dohyeonmd_open,
.release= dohyeonmd_release,
.read= dohyeonmd_read,
.write= dohyeonmd_write,
};
file operations 구조체를 이용하여 open release read write 를 정의 할 수 있다.
위 기능을 통해 user space 에서 system call 이 가능해진다. (자세한 내용은 아래 구현 참고)
Simple Device Driver 구현
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/poll.h>
#define dohyeonmd_dev_name "ryan dohyeonmd"
#define data_max_len 128
int dohyeonmd_major = 99;
static char data[data_max_len];
static int data_len;
static int dohyeonmd_open( struct inode *inode, struct file *filp )
{
printk("dohyeonmd_open\n");
data_len = 0;
return 0;
}
static ssize_t dohyeonmd_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
{
int copylen = count;
if (!buf) return -1;
if (count <= 0) return -1;
if (copylen > data_len)
copylen = data_len;
if (copylen > 0)
{
if (copy_to_user(buf,data,copylen*sizeof(char)))
{
return -1;
}
}
return copylen;
}
static ssize_t dohyeonmd_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos)
{
int copylen = count;
if(!buf) return -1;
if (copylen > data_max_len)
copylen = data_max_len;
if (copylen > 0)
{
if (copy_from_user(data, buf, copylen*sizeof(char)))
{
return -1;
}
}
data_len = copylen;
return copylen;
}
static int dohyeonmd_release( struct inode *inode, struct file *filp)
{
printk("dohyeonmd_release\n");
return 0;
}
static struct file_operations dohyeonmd_fops =
{
.owner=THIS_MODULE,
.open= dohyeonmd_open,
.release= dohyeonmd_release,
.read= dohyeonmd_read,
.write= dohyeonmd_write,
};
static int dohyeonmd_init(void)
{
dohyeonmd_major = register_chrdev( 0, dohyeonmd_dev_name, &dohyeonmd_fops );
if (dohyeonmd_major >= 0)
{
printk("register device %s Success (major=%d)\n", dohyeonmd_dev_name, dohyeonmd_major );
}
else
{
printk("register device %s Fail\n", dohyeonmd_dev_name);
return -EBUSY;
}
return 0;
}
static void dohyeonmd_exit(void)
{
unregister_chrdev( dohyeonmd_major, dohyeonmd_dev_name );
}
module_init(dohyeonmd_init);
module_exit(dohyeonmd_exit);
MODULE_AUTHOR("ryanclaire.blogspot.com");
MODULE_LICENSE("Daul BSD/GPL");
Makefile 구현
KERNDIR=/lib/modules/$(shell uname -r)/build
obj-m+=dohyeonmodule.o
objs+=dohyeonmodule.o
PWD=$(shell pwd)
default:
make -C $(KERNDIR) M=$(PWD) modules
clean:
make -C $(KERNDIR) M=$(PWD) clean
rm -rf *.ko
rm -rf *.o
사용 중인 kernel 에 따라 상이하며, 사용중인 커널에 맞게 make 빌드를 진행해야 한다.
KERNDIR 은 아래에서 확인 할 수 있다.
uname -r
make 가 install 안되어 있는 경우 아래 command 진행한다.
apt-get install make
make 를 진행하여 kernel object 확장자인 dohyeonmd.ko 를 획득 한다.
insmod 를 통해 디바이스 드라이버 등록을 완료 할 수 있다.
장치 파일 생성
/dev 아래에 디바이스 드라이버 모듈 장치를 생성하야 한다.
위 Device Drive 구현 에서 major number 를 99로 설정 한 것과 동일하게 해야한다.
mknod /dev/dohyeonmd c 99 0
dmesg 를 통해 결과를 확인 할 수 있다.
반응형
'OS > Linux' 카테고리의 다른 글
[Linux] vim 에디터 설치 (0) | 2022.01.20 |
---|---|
[Linux] Alias 에일리어스 등록하기 (0) | 2022.01.20 |
Linux bash 에서 oh my zsh agnoster 적용하기 (0) | 2020.12.17 |
Ubuntu /var/lib/dpkg/lock-frontend 잠금 파일을 얻을 수 없습니다. 해결하기 (0) | 2020.12.17 |
rsync 암호 서버 동기화 (0) | 2020.11.18 |