Dynamic Allocation of device numbers and dynamic generation of device nodes in Linux character drivers

Source: Internet
Author: User

From: http://www.cnblogs.com/zhuyp1015/archive/2012/05/22/2514008.html bird1015 blog

When writing a Linux kernel driver, if you do not dynamically generate a device number, you need to manually allocate the device number. It is possible that the device number you allocate will be the same as the existing device number and cause a conflict. Therefore, it is recommended that the device number be automatically assigned. Use the following functions:

Int alloc_chrdev_region (dev_t * dev, unsigned baseminor, unsigned count, const char * name)

This function must be passed to baseminor (usually 0), the number of devices to be allocated, and the device name, after this function is called, the device numbers automatically allocated are stored in dev.

When alloc_chrdev_region () is used to dynamically allocate device numbers, you must use the following methods in sequence:

 

Cdev_init (struct cdev * cdev, const struct file_operations * fops)

And

Cdev_add (struct cdev * p, dev_t dev, unsigned count)

Register the character device to the kernel. The above three functions can be used to dynamically generate device numbers.

You need to use:Unregister_chrdev_region (dev_t from, unsigned count)To release the device number.

 

After dynamically creating the device number, load the driver to the kernel through:Cat/proc/devicesCommand to view the device number

 

If the upper-layer application needs to access the driver, you need to create a device node for the driver.

If you need to manually create a device node, follow these steps: (assume that the device Number of the character device CDEV_ZHU is 254 found through cat/proc/devices)

$Mknod/dev/CDEV_ZHU c 254 0

 

If we dynamically create the driver, we need to do this:

Cdev_class = class_create (owner, name)// Cdev_class is of the struct class type.

Then use:

Device_create (_ cls, _ parent, _ devt, _ device, _ fmt)

After a device node is dynamically created, you must use the following command to uninstall the node:

Device_destroy (_ cls, _ device)AndClass_destroy (struct class * cls)

To destroy devices and classes.

The following is a set of test code: (this Code enables an application to access and modify a global variable "global_var" by opening the driver ")

/* DRIVER: globalvar. c */

# Include <linux/module. h>
# Include <linux/init. h>
# Include <linux/fs. h>
# Include <asm/uaccess. h>
# Include <asm/device. h> // The following three header files need to be added for dynamic creation.
# Include <linux/device. h>
# Include <linux/cdev. h>

 
MODULE_LICENSE ("GPL ");
 
# Define DEVICE_NAME "CDEV_ZHU"
Static struct class * cdev_class;
 
Static ssize_t globalvar_read (struct file *, char *, size_t, loff_t *);
Static ssize_t globalvar_write (struct file *, const char *, size_t, loff_t *);
 
// Initialize the file_operations struct of the character Device Driver
Struct file_operations globalvar_fops =
{
Read: globalvar_read,
Write: globalvar_write,
};

Static int global_var = 0; // global variable of the CDEV_ZHU Device

Dev_t dev = 0;// This is required to dynamically allocate device numbers and dynamically create device nodes.
Struct cdev dev_c;
 
Static int _ init globalvar_init (void)
{
Int ret, err;
 
// Register the device driver
 
Ret =Alloc_chrdev_region(& Dev, 0, 1, DEVICE_NAME); // dynamically allocates device numbers.
If (ret)
{
Printk ("globalvar register failure \ n ");
Unregister_chrdev_region (dev, 1 );
Return ret;
}
Else
{
Printk ("globalvar register success \ n ");
}

Cdev_init(& Dev_c, & globalvar_fops );
 
Err =Cdev_add(& Dev_c, dev, 1 );

If (err)
{
Printk (KERN_NOTICE "error % d adding FC_dev \ n", err );
Unregister_chrdev_region (dev, 1 );
Return err;
}
 
Cdev_class =Class_create(THIS_MODULE, DEVICE_NAME); // dynamically create a device Node
If (IS_ERR (cdev_class ))
{
Printk ("ERR: cannot create a cdev_class \ n ");
Unregister_chrdev_region (dev, 1 );
Return-1;
}
 Device_create(Cdev_class, NULL, dev, 0, DEVICE_NAME );
 
Return ret;
}
 
Static void _ exit globalvar_exit (void)
{
 
// Cancel the device driver

 Device_destroy(Cdev_class, dev );
 Class_destroy(Cdev_class );
 Unregister_chrdev_region(Dev, 1 );
Printk ("globalvar_exit \ n ");
}
 
Static ssize_t globalvar_read (struct file * filp, char * buf, size_t len, loff_t * off)
{
// Copy global_var from the kernel space to the user space
If (copy_to_user (buf, & global_var, sizeof (int )))
{
Return-EFAULT;
}
Return sizeof (int );
}
 
Static ssize_t globalvar_write (struct file * filp, const char * buf, size_t len, loff_t * off)
{
// Copy user space data to global_var of kernel space
If (copy_from_user (& global_var, buf, sizeof (int )))
{
Return-EFAULT;
}
Return sizeof (int );
}
 
Module_init (globalvar_init );
Module_exit (globalvar_exit );

/* Application: globalvartest. c */

# Include <sys/types. h>
# Include <sys/stat. h>
# Include <stdio. h>
# Include <fcntl. h>
Int main ()
{
Int fd, num;
// Open "/dev/CDEV_ZHU"
Fd = open ("/dev/CDEV_ZHU", O_RDWR, S_IRUSR | S_IWUSR );
If (fd! =-1)
{
// First read global_var
Read (fd, & num, sizeof (int ));
Printf ("The globalvar is % d \ n", num );
 
// Write global_var
Printf ("Please input the num written to globalvar \ n ");
Scanf ("% d", & num );
Write (fd, & num, sizeof (int ));
 
// Read global_var again
Read (fd, & num, sizeof (int ));
Printf ("The globalvar is % d \ n", num );
 
// Close "/dev/CDEV_ZHU"
Close (fd );
}
Else
{
Printf ("Device open failure \ n ");
}

Return 0;
}

Note: I modified the code of the book "programming for Linux devices in a simple way". It is easier to use dynamic device creation and dynamic generation of device numbers in projects, so I will share it here.

Use a simple makefile to convert (drive) globalvar. after c is compiled, use insmod globalvar. ko loads the driver to the kernel and then runs globalvartest. run the executable file generated by c to operate the global variables in the driver. You do not need to create a device node in the command line as in the book.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.