register_chrdrv()를 리눅스 커널 2.6 버전용으로 바꾸기

Linux Device Driver 중 Character device 의 코드를 보면 기존의 2.6 기준으로 수정되지 않은 코드들은 register_chrdrv() 함수를 사용하여 Character device를 등록하도록 되어 있다. register_chrdrv 함수의 원형은 다음과 같다.

int register_chrdev(unsigned int major, const char *name,
      const struct file_operations *fops)

그러나 2.6의 디바이스 드라이버들은 이와 다른 방식을 사용한다. register_chrdrv를 사용하는 방식은 Linux device driver 개정 3판을 보면 3장의 “예전 방식”이라는 부분에서 이를 다룬다. 예전 방식이 아닌 새로운 방식으로 작성하려면 register_chrdev 대신 register_chrdrv_region/alloc_chrdev_region 과 cdev_init, cdev_add 로 작성하면 된다.

register_chrdrv_region 함수는 원하는 디바이스의 번호를 미리 알고 있을 때 사용하고, alloc_chrdev_region 함수는 디바이스의 번호를 동적으로 할당받아 파라미터로 받는 dev_t 구조체 포인터를 이용해 dev_t 구조체에 넣는다.
register_chrdrv 대신 register_chrdrv_region을 사용하는 것으로 혼동할 수 있는데 그게 아닌 cdev_add 함수까지 사용하여야 한다. 실제 커널 소스의 register_chrdrv 함수를 보면 이런 과정이 구현되어 있음을 볼 수 있다.
cdev_add 함수를 사용하기 위해서는 struct cdev 구조체를 사용하여야 하는데 이 구조체를 초기화 시켜주는 함수가 cdev_init 이다. struct cdev 구조체 등을 사용하려면 <linux/cdev.h> 를 include하여야 한다. 다음은 사용 예이다.

#include <linux/kernel.h>
#include <linux/cdev.h>
#include <linux/fs.h>


struct file_operations dasom_fops;


static struct cdev dasom_cdev = {
    .owner = THIS_MODULE,
    .ops = &dasom_fops,

};


int _init dasom_init(void)
{
    dev_t dev;
    int err = 0;


    if(major) {
        dev = MKDEV(major, minor);
        err = register_chrdev_region(dev, 1, “dasomoli”);
    } else {
        err = alloc_chrdev_region(&dev, mior, 1, “dasomoli”);
        major = MAJOR(dev); 
    }
    if(err < 0) {
        err = -ENODEV;
        return err;
    }

    …
   
    cdev_init(&dasom_cdev, &dasom_fops);
    dasom_cdev.owner = THIS_MODULE;
    dasom_cdev.ops  = &dasom_fops;


    if(cdev_add(&dasom_cdev, dev, 1)) {
        printk(KERN_INFO”dasom: cdev creation failed.\n”);
        err = -ENODEV;
        goto error_label;
    }
   
    …
   
    return 0;
   
error_label:
    return err;
}

 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다