고급 개발자로 가는 길

OS/Linux

[Linux] Device Driver 모듈 개발

다크엔지니어 2021. 5. 16. 16:24
반응형

유저 커널 영역

 

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 를 통해 결과를 확인 할 수 있다.

반응형