Linux Device Driver 3 (1)-character device driver source code analysis

Source: Internet
Author: User

1. Call module_init (scull_init_module) in the insmod module. Let's take a look at this function: int scull_init_module (void)

II,

Int scull_init_module (void) <br/>{< br/> int result, I; // declare two integer variables result, I <br/> dev_t Dev = 0; // declare a dev_t type object Dev. The default initial value is 0 </P> <p> // the following code calls the alloc_chrdev_region method to dynamically generate the device number to Dev, the device name is "scull" and the master device number in Dev is extracted and paid to scull_major by calling the macro major (dev_t Dev) </P> <p> // the prototype of the alloc_chrdev_region function is: int alloc_chrdev_region (dev_t * Dev, unsigned int firstminor, unsigned int count, char * Name); </P> <p> // each parameter has the following meanings: </P> <p> // Dev _ T * Dev: dev_t pointer, which is the address of the variable (storing the generated device number) </P> <p> // firstminor: the first device number to be requested, usually 0. This document defines int scull_minor = 0; </P> <p> // count: the number of consecutive device numbers requested. Here is scull_nr_devs. This document defines: int scull_nr_devs = scull_nr_devs; </P> <p> // scull_nr_devs in the header file scull. </P> <p> // # ifndef scull_nr_devs <br/> // # define scull_nr_devs 4/* scull0 through scull3 */<br/> // # endif </P> <p> // Name: char pointer. Is the name of the device associated with the specified range. The "scull" name will appear in the/proc/devices and sysfs files </P> <p> If (scull_major) {<br/> Dev = mkdev (scull_major, scull_minor); <br/> result = register_chrdev_region (Dev, scull_nr_devs, "scull"); <br/>} else {// The default scull_major = 0; therefore, use the Dynamic Allocation Method <br/> result = alloc_chrdev_region (& Dev, scull_minor, scull_nr_devs, <br/> "scull "); <br/> scull_major = major (Dev); <br/>}< br/> If (result <0) {<br/> printk (kern_warnin G "scull: Can't Get Major % d/N", scull_major); <br/> return result; <br/>}</P> <p> // scull_devices: A pointer variable declared in the scull_dev structure: struct scull_dev * scull_devices; </P> <p> // The scull_dev structure is customized. Each scull device has a corresponding scull_dev structure. In scull. statement in H. </P> <p> // struct scull_dev {<br/> // struct scull_qset * data; /* pointer to the First Quantum set <br/> // int quantum;/* quantum size <br/> // int qset; /* large and small quantum set <br/> // unsigned long size;/* Total Amount of stored data */<br/> // unsigned int access_key; /* used by sculluid and scullpriv */<br/> // struct semaphore SEM;/* Mutual Exclusion semaphore */<br/> // struct cdev; /* character device structure */<br/> //}; <br/> // the prototype of the kmalloc function is void * kmalloc. (Size_t size, int flags); its function is to dynamically open up memory in the device driver or kernel module. each parameter has the following meanings: </P> <p> // size: the size of the memory to be allocated. in bytes. here is (the size of a scull_dev structure) * Number of devices. The number of devices is determined by scull_nr_devs as four </P> <p> // flags: the type of memory to be allocated. the most common gfp_kernel flag is used here. Green = get free page. </P> <p> // This function returns the first address of the allocated memory. The address is paid to scull_dev's pointer variable scull_devices </P> <p> // if the allocation is not successful, then goto fail </P> <p> // because kmalloc does not clear the acquired memory space, therefore, the memset function is called to clear the memory </P> <p> // the prototype of the memset function is void * memset (void * s, int C, size_t N ); the general function is to set the value of the first n Bytes of the memory space S to the value c. </P> <p> scull_devices = kmalloc (scull_nr_devs * sizeof (struct scull_dev), gfp_kernel); <br/> If (! Scull_devices) {<br/> result =-enomem; <br/> goto fail; /* make this more graceful */<br/>}</P> <p> memset (scull_devices, 0, scull_nr_devs * sizeof (struct scull_dev )); // reset the opened memory </P> <p> // initialize and register each device </P> <p> // 1. set the quantum size of each device to 4000 </P> <p> // 2. set the array size of each device to 1000 </P> <p> // 3. set the mutex semaphores of each device to 1. the prototype of the function is void init_mutex (struct semaphore * SEM); </P> <p> // This function is used to initialize a mutex lock, that is, it sets the semaphores SEM value to 1. </P> <p> // 4. Use the custom function scull_setup_cdev to initialize the character device structure and add it to the system (register the device). A total of four devices are added. The function is defined as follows: </P> <p> // static void scull_setup_cdev (struct scull_dev * Dev, int index) <br/> // {<br/> // int err, devno = mkdev (scull_major, scull_minor + index ); // scull_major that has been dynamically allocated is used here <br/> // The following steps are very important !!! Is the basic process of registering an independent cdev device !!! <Br/> // cdev_init (& Dev-> cdev, & scull_fops); // initialize struct cdev <br/> // Dev-> cdev. owner = this_module; // initialize cdev. owner <br/> // Dev-> cdev. ops = & scull_fops; // initialize cdev. ops <br/> // err = cdev_add (& Dev-> cdev, devno, 1); // After the cdev structure is set, inform the kernel of the structure <br/> /// * fail gracefully if need be */<br/> // If (ERR) <br/> // printk (kern_notice "error % d adding scull % d", err, index ); <br/> //} </P> <p> for (I = 0; I <scull_nr_devs; I ++) {<br/> scull_devices [I]. quantum = scull_quantum; <br/> scull_devices [I]. qset = scull_qset; <br/> init_mutex (& scull_devices [I]. SEM); <br/> scull_setup_cdev (& scull_devices [I], I ); <br/>}</P> <p>/* at this point call the init function for any friend device */</P> <p> // not considered here other devices </P> <p> Dev = mkdev (scull_major, scull_minor + scull_nr_devs); </P> <p> Dev + = scull_p_init (Dev); </P> <p> Dev + = scull_access_init (Dev); <br/>

 

The device has been initialized.

Summarize the initialization steps of the module (only the general situation is taken into account, not the special case of Scull ).

Step 1: dynamically generate the device ID. The key functions of this step are as follows:

Int alloc_chrdev_region (dev_t * Dev, unsigned int firstminor, unsigned int count, char * Name );

Step 2: assign a character device structure. The key functions of this step are as follows:

Struct cdev * cdev_alloc (void );

(In scull, kmalloc is used to open up memory for the device)

Step 3: Initialize and add the device. The key functions of this step are as follows:

Void cdev_init (struct cdev * cdev, struct file_operations * FoPs );
Int cdev_add (struct cdev * Dev, dev_t num, unsigned int count );

Step 2 and Step 3 are collectively referred to as "Registration of character devices"

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.