Third, the equipment driver under the UNIX system 3.1, the basic structure of the device driver under UNIX In the UNIX system, in terms of the user program, the device driver hides the specific details of the device, providing a consistent interface for a variety of different devices. Generally, it is to map the device into a special device file, and the user program can operate on this device file like other files. UNIX supports two standard interfaces for hardware devices: block special equipment files and character special equipment files, the device accessed by the block (character) special device file is called a block (character) device or a block (character) device interface. The block device interface only supports block-oriented I / O operations, all I / O operations are performed in the I / O buffer in the kernel address space, which can support almost any length and any position I / O request, ie Provide random access. The character device interface supports the character-oriented I / O operation, which is not responsible for managing your own buffer structure without the fast cache of the system. The character device interface only supports sequential access, generally cannot perform an I / O request of any length, but to limit the length of the I / O request must be a multiplication of the basic blocks required by the device. Obviously, the serial card driven by this program can only provide sequential access, which belongs to a character device, so the following discussion is only related to the characteristic device interface when the two devices are different. The device is identified by a master number and a secondary device number. The main device number uniquely identifies the device type, that is, the device driver type, which is the index of the device entry in the block device table or character device table. The secondary device number is only interpreted by the device driver, typically used to identify the device involved in the I / O request in several possible hardware devices. The device driver can be divided into three main components: (1) Automatic configuration and initialization subroutine, which is responsible for detecting whether the hardware device to be driven does not work properly. If the device is normally, the software status of this device and its related, device driver need is initialized. This part of the driver is called once when it is initialized. (2) Serving the subroutine of the I / O request, also known as the upper half of the driver. Calling this part is due to the result of the system call. This part of the program is executing, the system still thinks that the process of being called belongs to the same process, but the user state has become a core state, with the operating environment of the user program that is called by this system, so it can be called SLEEP. () Wait with the function of the process running environment. (3) Interrupt service subroutine, also known as the lower half of the driver. In the UNIX system, the interrupt service subroutine of the device driver is not called directly from the interrupt vector table, but is received by the UNIX system to receive the hardware interrupt, and then the interrupt service subroutine is called. The interrupt can be generated when any process is running, so when the interrupt service program is called, it cannot rely on any process, and any function related to the process running environment cannot be called. Since the device driver typically supports several devices of the same type, it is generally included with one or more parameters when the system calls the interrupt service subroutine, and the device that uniquely identifies the request service. In the system, the access of the I / O device is performed by a set of fixed entry points, which is provided by the device driver of each device. In general, the character device driver provides the following entry points: (1) Open entry point. Open the device to prepare the I / O operation. Opening the character special equipment file, the Open entry point of the device is called. The Open subroutine must prepare the I / O operation to be made, such as clearing the buffer. If the device is exclusive, only one program can access this device at the same time, then the Open subroutine must set some flags to indicate that the device is busy. (2) Close entry point. Close a device. When the device is used last time, the Close subroutine is called. Excise equipment must mark the device again. (3) READ entry point. Read the data from the device.
For I / O operations with buffers, it is generally read from the buffer. The read subroutine will be called for the character special device file. (4) WRITE entry point. Write data on the device. For I / O operations with buffers, it is generally written to the buffer in the buffer. Write subroutine is called to write a Write subroutine to write a word special device file. (5) IOCTL entry point. Perform a read and write operations. (6) SELECT entry point. Check the device to see if the data is readable or if the device can be used to write data. The SELECT system call uses the SELECT entry point when checking the file descriptor related to the device special file. If the device driver does not provide one of the above entry points, the system will replace it with the default subroutine. There are also other entry points for different systems. 3.2, the device driver under the Linux system is specifically to the Linux system, the set of entry points provided by the device driver are described by a structure to the system, this structure is defined as: #include
INT (* open * inode, struct file * inode, struct file * inf); int (* fsync) (Struct Inode * Inode, Struct File * Filp) ;}; Struct Inode provides information about special device file / dev / driver (assuming this device named driver), it is defined as: #include
Struct file is mainly used to use the device driver corresponding to the file system. Of course, other device drivers can also use it. It provides information about the file opened, defined as: #include
In the structural file_operations, the entry point position provided by the device driver is: (1) Lseek, the position of the mobile file pointer, obviously can only be used to random access. (2) READ, read operation, parameter buf is a buffer that stores read results, and count is the length of the data to be read. The return value is an error indicating an error in the reading operation, otherwise returns the number of bytes actually read. For characters, the number of bytes required to be read and the number of actual read bytes returned must be inode-> i_blksize multiple. (3) WRITE, write operation, similar to read. (4) READDIR, obtain the next directory entry point, only the device driver related to the file system is used. (5) SELEC, select the selection, if the driver does not provide a SELECT entry, the SELECT operation will consider that the device is ready for any I / O operation. (6) IOCTL, other operations other than read, write, parameter cmd is a custom command. (7) MMAP, used to map the contents of the device to the address space, generally only the block device driver is used. (8) Open, open the device to prepare I / O operations. Returning 0 indicates that the opening is successful, and the return negative number is failed. If the driver does not provide an Open entry, as long as the / dev / driver file is considered to open success. (9) Release, ie the Close operation. The entry point provided by the device driver is registered to the system when the device driver is initialized so that the system is called when appropriate. In the Linux system, the character-type device driver is registered to the system by calling Register_chrdev. Register_chrdev is defined as: #include
They are defined as: #include
Thus the need to use several functions as follows: int check_region (unsigned int from, unsigned int extent); void request_region (unsigned int from, unsigned int extent, const char * name); void release_region (unsigned int from, unsigned int extent); The parameter when calling these functions is: from the start address of the I / O port applied; EXTENT is the number of ports starting from the FROM; name is a device name, will appear in the / proc / Ioports file. Check_region returns 0 indicates that I / O port is idle, otherwise it is being used. After the I / O port is applied, you can access the I / O port: #include
In the device driver, some system functions may also be used: #include