Another way to write character device

For the previous method of using register_chrdev function to register a character device driver actually has not been upgraded to the 2.6 version of the kernel driver code. Although this way is simple to understand (it may be simply understood as a major number of the drive index into the array of structures called file_operations chrdevs in, and when the application layer calls the open function, the device will be the main character by device number to find the open function call file_operations structure) from chrdevs array, but there is a drawback is that for the same major number of different 256 minor numbers can call the same open, causing such device drivers available It can be up to 256. So after kernel version 2.6, there is a dev_t type, which is used to save the device ID, which is a 32-bit number, 12 bits are used for the major number, and the remaining 20 for the secondary device number. A major number and the same, different numbers of the device may represent a different device. In this case, it can have a maximum drive 4G devices can be used.

 

1, the wording of character device drivers

In previous methods the preparation of such a device is a character:
1, determining the device number
2 is assigned, is provided a structure file_operations
3, register_chrdev (device number, name, file_operations structure)
4, entry function
5, the export function

 

In the 2.6 kernel, a new method of writing a character device is this:
to major and minor device numbers to find file_operations structure.
Expand the register_chrdev:
. 1, alloc_chrdev_region / register_chrdev_region (from the (main and secondary) to (primary, secondary + n) corresponds file_operations structure)
2, cdev_init
. 3, cdev_add

 

2, a new method of writing character device drivers written and tested

Listed directly to the driver, realized by the following two drivers, respectively hello_ops, and hello2_ops. Then hello_ops may correspond to the minor device number 0 and the character device file 1, and the corresponding hello2_ops minor number 2 character device file.

#include <Linux / the module.h> 
#include <Linux / kernel.h> 
#include <Linux / fs.h> 
#include <Linux / init.h> 
#include <ASM / the io.h>             // containing function iomap iounmap function 
#include <ASM / uaccess.h>        // containing copy_from_user function 
#include <Linux / device.h>       // containing the class associated handler 
#include <ASM / Arch / regs-gpio.h> // containing S3C2410_GPF0 and other related 
#include <Linux / irq.h>          // containing IRQ_HANDLED \ IRQ_TYPE_EDGE_RISING 
#include <ASM-ARM / irq.h>        // containing IRQT_BOTHEDGE trigger type 
#include <linux / interrupt.h>   // contains request_irq, free_irq function
#include <linux/cdev.h>

/* 1、确定主设备号 */
static int major;

static int hello_open (struct inode * inode, struct file * file)
{
    printk("hello_open\n");
    return 0;
}

static int hello2_open (struct inode * inode, struct file * file)
{
    printk("hello2_open\n");
    return 0;
}
/* 2、构造file_operations */
static struct file_operations hello_ops = {
    .owner   = THIS_MODULE,
    .open    =  hello_open,
};

/* 2、构造file_operations */
static struct file_operations hello2_ops = {
    .owner   = THIS_MODULE,
    .open    =  hello2_open,
};

#define HELLO_CNT 2
static struct cdev hello_cdev;
static struct cdev hello2_cdev;

static struct classCLS *; // class 

static  int hello_init ( void ) 
{ 
    the dev_t DevID; 
    
    / * . 3, to tell the kernel * / 
#if 0 
    the register_chrdev ( 0 , " Hello " , & hello_ops); / * lead (major, 0), (major , 1), ... (major, 255 ) corresponds hello_ops * / 
#else 
    IF (Major) 
    { 
        DevID = mkdev (Major, 0 ); 
        register_chrdev_region (DevID, HELLO_CNT, " Hello " ); / * (Major, 0- 1) corresponding to hello_ops, (major, 2-255) does not correspond to*/
    } 
    else 
    {
        alloc_chrdev_region(&devid, 0, HELLO_CNT, "hello");/* (major, 0-1)对应hello_ops,(major, 2-255)都不对应 */
        major = MAJOR(devid);
    }
    
    cdev_init(&hello_cdev, &hello_ops);
    cdev_add(&hello_cdev, devid, HELLO_CNT);
    
    devid = MKDEV(major, 2);
    register_chrdev_region(devid, 1, "hello2");/* (major, 2)对应hello2_ops,(major, 3-255)都不对应 */
    
    cdev_init(&hello2_cdev, &hello2_ops);
    cdev_add(&hello2_cdev, devid, 1);
        
#endif

    cls = class_create(THIS_MODULE, "hello");//创建类
    class_device_create(cls, NULL, MKDEV(major,0), NULL,"hello0");/* /dev/hello0 */
    class_device_create(cls, NULL, MKDEV(major,1), NULL,"hello1");/* /dev/hello1 */
    class_device_create(cls, NULL, MKDEV(major,2), NULL,"hello2");/* /dev/hello2 */
    class_device_create(cls, NULL, MKDEV(major,3), NULL,"hello3");/* /dev/hello3 */
    return 0;
}

static void hello_exit(void)
{
    class_device_destroy(cls, MKDEV(major,0));
    class_device_destroy(cls, MKDEV(major,1));
    class_device_destroy(cls, MKDEV(major,2));
    class_device_destroy(cls, MKDEV(major,3));
    class_destroy(cls);
    
    cdev_del(&hello_cdev);
    unregister_chrdev_region(MKDEV(major, 0), HELLO_CNT);
    
    cdev_del(&hello2_cdev);
    unregister_chrdev_region(MKDEV(major, 2), 1);
}


module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

 

Then write a test program to test it, this test procedure can be found in the appropriate device driver by opening different character device file.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

/* 
 * ./hello_test <dev>
 */

void printf_usage(char *file)
{
    printf("%s <dev>\n", file);
}
 
int main(int argc, char **argv)
{
    int fd;
    if(argc != 2)
    {
        printf_usage(argv[0]);
        return 0;
    }
    
    fd = open(argv[1], O_RDWR);
    
    if(fd <0)
    {
        printf("can't open %s\n", argv[1]);
    }
    else
    {
        printf("can open %s\n", argv[1]);
    }
    return 0;
}

The following test results, the test results can be seen from / dev / hello0 ~ 3 major number of these four files are character device 252. Wherein the secondary device is a file corresponding 0,1 hello_ops; minor file 2 corresponding hello2_ops. This test results demonstrate the same master, different minor number may correspond to different drivers.

 

 

Guess you like

Origin www.cnblogs.com/andyfly/p/11273045.html