SW 개발

Linux : Device Driver 만들때 major / minor 를 정해서 만들기...

. . . 2013. 10. 25. 14:19
반응형

자료출처 : http://www.makelinux.net/ldd3/chp-3-sect-2


디바이스 드라어비 만들때...

major / minor number 를 정해서 만들수있다.


다 필요없이 코드르 보면 다음과같다.


주번호 부번호 할당하여 char device 만들기예제


if (scull_major) {
    dev = MKDEV(scull_major, scull_minor);
    result = register_chrdev_region(dev, scull_nr_devs, "scull");
else {
    result = alloc_chrdev_region(&dev, scull_minor, scull_nr_devs,
            "scull");
    scull_major = MAJOR(dev);
}
if (result < 0) {
    printk(KERN_WARNING "scull: can't get major %dn", scull_major);
    return result;
}


근데 주의해야할점은 커널측에서 미리 reserved 해논 major / minor 가 있다는것이다.

그내용은 커널문서를 확인하면 알수있다.


work/core/qlinux/Documentation/devices.txt


내용을 잠깐 살펴보면..


 232 char    Biometric Devices

         0 = /dev/biometric/sensor0/fingerprint  first fingerprint sensor on first device

         1 = /dev/biometric/sensor0/iris     first iris sensor on first device

         2 = /dev/biometric/sensor0/retina   first retina sensor on first device

         3 = /dev/biometric/sensor0/voiceprint   first voiceprint sensor on first device

         4 = /dev/biometric/sensor0/facial   first facial sensor on first device

         5 = /dev/biometric/sensor0/hand     first hand sensor on first device

           ...

         10 = /dev/biometric/sensor1/fingerprint first fingerprint sensor on second device

           ...

         20 = /dev/biometric/sensor2/fingerprint first fingerprint sensor on third device

           ...


 233 char    PathScale InfiniPath interconnect

         0 = /dev/ipath        Primary device for programs (any unit)

         1 = /dev/ipath0       Access specifically to unit 0

         2 = /dev/ipath1       Access specifically to unit 1

           ...

         4 = /dev/ipath3       Access specifically to unit 3

         129 = /dev/ipath_sma    Device used by Subnet Management Agent

         130 = /dev/ipath_diag   Device used by diagnostics programs


 234-239     UNASSIGNED


 240-254 char    LOCAL/EXPERIMENTAL USE


 240-254 block   LOCAL/EXPERIMENTAL USE

         Allocated for local/experimental use.  For devices not

         assigned official numbers, these ranges should be

         used in order to avoid conflicting with future assignments.


 255 char    RESERVED


 255 block   RESERVED


         This major is reserved to assist the expansion to a

         larger number space.  No device nodes with this major

         should ever be created on the filesystem.

         (This is probably not true anymore, but I'll leave it

         for now /Torben)


별로 쓸수있는데가 없군;;


하지만 리눅스 커널 2.6 들어서면서 major number 를 256개 이상쓸수있게 커널이 수정되었기에...

뒷번호를 쓰면될듯하다.


자동으로 node 만드는 스크립트..

부팅시 다음과같은 스크립트로 노드르 자동으로도 만들수있다.

  (그래도 왠만하면 그냥 파일시스템 만들때 만드는게 나을듯....)


#!/bin/sh

module="scull"

device="scull"

mode="664"


# invoke insmod with all arguments we got

# and use a pathname, as newer modutils don't look in . by default

/sbin/insmod ./$module.ko $* || exit 1


# remove stale nodes

rm -f /dev/${device}[0-3]


major=$(awk "\\$2=  =\"$module\" {print \\$1}" /proc/devices)


mknod /dev/${device}0 c $major 0

mknod /dev/${device}1 c $major 1

mknod /dev/${device}2 c $major 2

mknod /dev/${device}3 c $major 3


# give appropriate group/permissions, and change the group.

# Not all distributions have staff, some have "wheel" instead.

group="staff"

grep -q '^staff:' /etc/group || group="wheel"


chgrp $group /dev/${device}[0-3]

chmod $mode  /dev/${device}[0-3]



실제 소스코드예제..

static int __init cs5535_gpio_init(void)
{
    dev_t   dev_id;
    u32 low, hi;
    int retval;

    if (pci_dev_present(divil_pci) == 0) {
        printk(KERN_WARNING NAME ": DIVIL not foundn");
        return -ENODEV;
    }

    /* Grab the GPIO I/O range */
    rdmsr(MSR_LBAR_GPIO, low, hi);

    /* Check the mask and whether GPIO is enabled (sanity check) */
    if (hi != 0x0000f001) {
        printk(KERN_WARNING NAME ": GPIO not enabledn");
        return -ENODEV;
    }

    /* Mask off the IO base address */
    gpio_base = low & 0x0000ff00;

    /**
     * Some GPIO pins
     *  31-29,23 : reserved (always mask out)
     *  28       : Power Button
     *  26       : PME#
     *  22-16    : LPC
     *  14,15    : SMBus
     *  9,8      : UART1
     *  7        : PCI INTB
     *  3,4      : UART2/DDC
     *  2        : IDE_IRQ0
     *  0        : PCI INTA
     *
     * If a mask was not specified, be conservative and only allow:
     *  1,2,5,6,10-13,24,25,27
     */

    if (mask != 0)
        mask &= 0x1f7fffff;
    else
        mask = 0x0b003c66;

    if (!request_region(gpio_base, CS5535_GPIO_SIZE, NAME)) {
        printk(KERN_ERR NAME ": can't allocate I/O for GPIOn");
        return -ENODEV;
    }

    if (major) {
        dev_id = MKDEV(major, 0);
        retval = register_chrdev_region(dev_id, CS5535_GPIO_COUNT,
                        NAME);
    } else {
        retval = alloc_chrdev_region(&dev_id, 0, CS5535_GPIO_COUNT,
                         NAME);
        major = MAJOR(dev_id);
    }

    if (retval) {
        release_region(gpio_base, CS5535_GPIO_SIZE);
        return -1;
    }

    printk(KERN_DEBUG NAME ": base=%#x mask=%#lx major=%dn",
           gpio_base, mask, major);

    cdev_init(&cs5535_gpio_cdev, &cs5535_gpio_fops);
    cdev_add(&cs5535_gpio_cdev, dev_id, CS5535_GPIO_COUNT);

    return 0;
}
 


반응형