Linux Kernel development-simple character Device Driver (I)

Source: Internet
Author: User
To put it bluntly, let's first introduce several structures related to character devices that must be known, and then combine themCodeDetailed description.
 
Part 1 necessary device structure
 
1) in Linux 2.6, The cdev struct is used to represent character devices:StructCdev {StructKobject kobj;// Embedded kobject objectStructModule * owner;// ModuleStructFile_operations * OPS;// File operation structureStructList_head list; dev_t dev;// Device number. The length is 32 bits. The height of 12 is the main device number, and the height of 20 bits is the device number.Unsigned IntCount ;};
You can use the following macros to obtain the Primary and Secondary device numbers from dev_t: You can also use the following macros to generate dev_t through the Primary and Secondary device numbers: Major (dev_t Dev); mkdev (INT major, int minor ); minor (dev_t Dev); Note: a large number of devices can be accommodated in the 2.6 kernel, while the previous kernel version was limited to 255 master device numbers and 255 master device numbers. 2) The member function in the file_operations struct is a character device driver. Program Content of the subject in the design. These functions are actually called by the system during Linux open (), write (), read (), close () and other system calls. The current file_operations structure has become very large. Here we are concerned about several functions related to my device program. We will use them later. We will not mention them too late:
Static Const StructFile_operations globalmem_fops = {. Owner = this_module,. llseek = globalmem_llseek,// Modify the current read/write location of a file and return the new location. If an error occurs, a negative value is returned..Read= Globalmem_read ,.Write= Globalmem_write,. IOCTL = globalmem_ioctl,// The implementation of device-related control commands. The kernel can identify some control commands (in this case, you do not need to call IOCTL(). If the device does not provide this function and the kernel does not recognize this command,-einval is returned ..Open= Globalmem_open,. Release = globalmem_release ,};
 
 
3) The file structure is not associated with the file in the user space. strcut file is a kernel structure that does not appear in the user program. It represents an open file (not limited to the device driver, each opened file in the system has a corresponding file structure in the kernel space ). It is created when the kernel is open and passed to all functions operated on the file until the final close function. After all instances of the file are closed, the kernel will release the data structure. 4) The kernel uses its node structure to internally represent files, which is different from the file structure. The latter indicates the opened file descriptor. For a single file, there may be many file structures that indicate open file descriptors, but they all point to a single inode structure. There are only two useful fields in it and our driver: dev_t I _rdev; // pair indicating the inode structure of the device file. This field contains the real device number struct cdev * I _cdev; // indicates the internal structure of the character device kernel. When inode points to a character device file, this field contains a pointer to the struct cdev structure. Can I use the following two macros to obtain the master device number and the device number from inode:
 
Unsigned IntIminor (StructInode * inode );Unsigned IntImajor (StructInode * inode );
For program portability, we should use the above macro instead of directly operating I _rdev. Part 2 Source code Details
Necessary header files# Include <Linux/module. h> # include <Linux/types. h> # include <Linux/Fs. h> # include <Linux/errno. h> # include <Linux/mm. h> # include <Linux/sched. h> # include <Linux/init. h> # include <Linux/cdev. h> # include <ASM/Io. h> # include <ASM/System. H> # include <ASM/uaccess. h>

 
# Define globalmem_size 0x1000/* The global memory size is 4 kb */ 
 
# Define mem_clear 0x1// Reset the global memory
 
# Define globalmem_major 150// The default master device Number of globalmem
 
StaticGlobalmem_major = globalmem_major;
 
 
// Globalmem device structure
StructGlobalmem_dev
{
StructCdev;
Unsigned CharMem [globalmem_size];// Global memory
};
 Struct Globalmem_dev * globalmem_devp; // Device structure pointer  // File opening function  Int Globalmem_open ( Struct Inode * inode, Struct File * filp) {filp-> private_data = globalmem_devp; Return 0 ;}// File release function  Int Globalmem_release ( Struct Inode * inode, Struct File * filp ){ Return 0 ;} // Globalmem_ioctl Function  Static   Int Globalmem_ioctl ( Struct Inode * inodep, Struct File * filp, Unsigned   Int CMD, Unsigned  Long Arg ){ Struct Globalmem_dev * Dev = filp-> private_data; Switch (CMD ){ Case Mem_clear: // Clear global memory Memset (Dev-> MEM, 0, globalmem_size); printk (kern_info" Globalmem is set to zero \ n "); Break ; Default : Return -Einval; // Other unsupported commands } Return 0 ;}// Globalmem_read Function  Static Ssize_t globalmem_read ( Struct File * filp, Char _ User * Buf, size_t size, loff_t * PPOs ){ Unsigned   Long P = * PPOs; Unsigned   Int Count = size; Int Ret = 0; Struct Globalmem_dev * Dev = filp-> private_data; // Obtain the device structure pointer  // Analyze and obtain valid write lengths  If (P> = globalmem_size) Return Count? -Enxio: 0; If (Count> GLOBALMEM_SIZE-p) // If you want to read less than actually available Count = GLOBALMEM_SIZE-p; If (Copy_to_user (BUF ,( Void *) (Dev-> mem + p), count) {ret =-efault ;} Else {* PPOs + = count; ret = count; printk (kern_info" Read % d byte (s) from % d ", Count, P );} Return RET ;} // Globalmem_write  Static Ssize_t globalmem_write (Struct File * filp, Const   Char _ User * Buf, size_t size, loff_t * PPOs ){ Unsigned   Long P = * PPOs; Unsigned   Int Count = size; Int Ret = 0; Struct Globalmem_dev * Dev = filp-> private_data; // Obtain the device structure pointer  // Analyze and obtain valid write lengths  If (P> = globalmem_size) Return Count? -Enxio: 0; If (Count> GLOBALMEM_SIZE-p) // If you want to read less than actually available Count = GLOBALMEM_SIZE-p; If (Copy_from_user (Dev-> mem + P, Buf, count) ret =-efault; Else {* PPOs + = count; ret = count; printk (kern_info" Written % d bytes (s) from % d \ n ", Count, P );} Return RET ;} // Globalmem_seek Function  Static Loff_t globalmem_llseek ( Struct File * filp, loff_t offset, Int Orig) {loff_t ret = 0; Switch (Orig ){ Case 0: // Offset starting from the beginning of the file  If (Offset <0) {ret =-einval; Break ;} If (( Unsigned   Int ) Offset> globalmem_size) // Offset out of bounds {Ret =-einval; Break ;} Filp-> f_pos = ( Unsigned   Int ) Offset; ret = filp-> f_pos;Break ; Case 1: // Offset from the current position  If (Filp-> f_pos + offset)> globalmem_size) // Offset out of bounds {Ret =-einval; Break ;} If (Filp-> f_pos + offset) <0) {ret =-einval; Break ;} Filp-> f_pos + = offset; ret = filp-> f_pos; Break ; Default : Ret =-einval; Break ;} Return RET ;}

The preceding section describes the basic and important data structures involved in Linux simple character devices, as well as all the operations related to file_operations in the source code section.

Open (), write (), read (), close () and other system calls are finally called. These are directly copied from the source code. Both the order and structure maintain the integrity of the actual code. They can be copied to the next part for actual testing.

 

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.