Development of PCI driver in Linux (2)

Source: Internet
Author: User

Ii. Linux driverProgramFramework

Linux regards all external devices as a special type of files, which are called "Device Files". If a system call is an interface between the Linux kernel and applications, the device driver can be seen as an interface between the Linux kernel and external devices. The device driver shields the application from the implementation details of the hardware, so that the application can operate the external device like an ordinary file.

1. Character devices and block Devices

Linux abstracts the processing of hardware. All hardware devices can be viewed as common files: they can be used and operated.CompositionThe same and Standard System Call interfaces are used to complete open, close, read/write, and I/O control operations. The main task of the driver is to implement these System Call functions. All hardware devices in Linux are represented by a special device file. For example, the first IDE hard disk in the system is represented by/dev/hda. Each device file pair should have two device numbers: one is the master device number, which identifies the device type and the driver used by the device; the other is the secondary device number, identifies different hardware devices that use the same device driver. The master device number of the device file must be the same as the master device number applied by the device driver when you log on to the device. Otherwise, the user process will not be able to access the device driver.

In Linux, there are two main types of device files: character devices and Block devices. Character devices perform I/O operations one by one in bytes. When a read/write request is sent to a character device, the actual hardware I/O occurs immediately, generally, the cache in character devices is dispensable and does not support random access. A block device uses a piece of system memory as the buffer. When a user process requests read and write requests to the device, the driver first checks the content in the buffer, if the data in the buffer can meet the user's requirements, the corresponding data will be returned. Otherwise, the corresponding request function will be called for actual I/O operations. Block devices are designed for disks and other slow devices. The objective is to avoid excessive CPU time consumption to wait for the Operation to complete. Generally, PCI cards generally belong to character devices.

The primary device numbers of all registered hardware devices (I .e. drivers loaded) can be obtained from the/proc/devices file. You can use the mknod command to create a device file of the specified type and assign the corresponding primary device number and secondary device number to the file. For example, the following command:

[Root @ Gary root] # mknod/dev/lp0 C 6 0

A device file with the primary device number 6 and the secondary device number 0 is created. When an application calls a device file, the Linux kernel calls the corresponding Driver Based on the device type and master device Number of the file and enters the core State from the user State, then, the driver determines the device number, and finally completes the operation on the corresponding hardware.

2. Device Driver Interface

The I/O subsystem in Linux provides a unified standard device interface to other parts of the kernel, which is completed through the data structure file_operations in include/Linux/fs. h:

Struct File_operations {
Struct Module * Owner ;
Loff_t ( * Llseek )( Struct File * , Loff_t , Int );
Ssize_t ( * Read )( Struct File * , Char * , Size_t , Loff_t * );
Ssize_t ( * Write )( Struct File * , Const Char * , Size_t , Loff_t * );
Int ( * Readdir )( Struct File * , Void * , Filldir_t );
Unsigned Int ( * Poll )( Struct File * , Struct Poll_table_struct * );
Int ( * IOCTL )( Struct Inode * , Struct File * , Unsigned Int , Unsigned Long );
Int ( * MMAP )( Struct File * , Struct Vm_area_struct * );
Int ( * Open )( Struct Inode * , Struct File * );
Int ( * Flush )( Struct File * );
Int ( * Release )( Struct Inode * , Struct File * );
Int ( * Fsync )( Struct File * , Struct Dentry * , Int Datasync );
Int ( * Fasync )( Int , Struct File * , Int );
Int ( * Lock )( Struct File * , Int , Struct File_lock * );
Ssize_t ( * Readv )( Struct File * , Const Struct Iovec * , Unsigned Long , Loff_t * );
Ssize_t ( * Writev )( Struct File * , Const Struct Iovec * , Unsigned Long , Loff_t * );
Ssize_t ( * Sendpage )( Struct File * , Struct Page * , Int , Size_t , Loff_t * , Int );
Unsigned Long ( * Get_unmapped_area )( Struct File * , Unsigned Long ,
Unsigned Long , Unsigned Long , Unsigned Long );
};
When an application performs operations on device files such as open, close, read, and write, the Linux kernel accesses the functions provided by the driver through the file_operations structure. For example, when an application reads a device file, the kernel calls the READ function in the file_operations structure.

2. Device Driver Module

In Linux, device drivers can be compiled in two ways. One is to directly and statically compile the program into a part of the kernel, and the other is to compile the program into a module that can be dynamically loaded. If it is compiled into the kernel, the size of the kernel will be increased, and the source file of the kernel will be changed, and it cannot be dynamically uninstalled, which is not conducive to debugging. We recommend that you use the module method.

In essence, a module is also a part of the kernel. Unlike common applications, it cannot call C or C ++ library functions in user mode, you can only call functions provided by the Linux kernel. You can view all functions provided by the kernel in/proc/ksyms.

When writing a driver in the module mode, you must implement two essential functions: init_module () and cleanup_module (), and at least include <Linux/krernel. h> and <Linux/module. h> two header files. When compiling the kernel module with GCC, you need to add the-dmodule-d1_kernel _-dlinux parameters to compile the generated modules (generally. o file) You can use the command insmod to load the Linux kernel to become an integral part of the kernel. At this time, the kernel will call the function init_module () in the module (). When this module is not required, run the rmmod command to uninstall the module. The cleanup_module () function in the module is called in the kernel (). You can run the lsmod command to view the loaded modules and the number of users using the modules at any time.

3. device driver structure

Understanding the basic structure (or framework) of the device driver is very important for developers. the Linux device driver can be roughly divided into the following parts: driver registration and cancellation, device opening and releasing, device read/write operations, device control operations, device interruption and polling processing.

Driver registration and logout

Adding a driver to the system means giving it a master device number. This can be done by calling register_chrdev () or register_blkdev () during the driver initialization process. When you disable a character device or block device, you must call unregister_chrdev () or unregister_blkdev () to log out the device from the kernel and release the occupied master device number.

Enable and release a device

The device is opened by calling the function open () in the file_operations structure, which is used by the driver to complete initialization for future operations. In most drivers, open () usually needs to do the following:

Check for device errors, such as the device is not ready. If it is enabled for the first time, the hardware device is initialized. Identifies the device number. If necessary, update the current position pointer f_ops for read/write operations. Allocate and fill in the data structure to be placed in file-> private_data. Use count to increase by 1.

Releasing a device is done by calling the function release () in the file_operations structure. This device method is also called close (), which works exactly opposite to open, generally, you need to do the following:

Use count minus 1. Release the memory allocated in file-> private_data. If 0 is used, disable the device.Read/write operations on devices

The read/write operations on character devices are relatively simple. You can simply use the read () and write () functions. However, if it is a block device, you need to call the functions block_read () and block_write () to read and write data. These two functions will add read and write requests to the device request table, so that the Linux kernel can optimize the request sequence. Because the operation is performed on the memory buffer rather than the device directly, the read/write speed can be greatly accelerated. If there is no data to be read in the memory buffer, or you need to perform a write operation to write data to the device, you need to perform real data transmission by calling the request_fn () function in the data structure blk_dev_struct ().

Device Control Operations

In addition to read/write operations, applications sometimes need to control the device, which can be done through the ioctl () function in the device driver. The usage of IOCTL () is closely related to a specific device. Therefore, you need to perform a specific analysis based on the actual situation of the device.

Device interruption and polling

For hardware devices that do not support interruption, you must take turns to query the device status during read/write operations to determine whether to continue data transmission. If the device supports interruption, you can perform the operation as interrupted.

Read the full text

category: View comments in classic articles

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.