I. What is IOCTL?
IOCTL is a function used by the device driver to manage the device's I/O channels. The management of the I/O channel is to control some features of the device, such as the Serial Transmission baud rate and the motor speed. The number of calls is as follows:
Int IOCTL (int fd, IND cmd ,...); FD is the File Identifier returned by the open function when the user program opens the device. CMD is the control command of the user program on the device. As for the ellipsis, It is a supplement parameter, generally, there is at most one, or is not related to the meaning of CMD.
The ioctl function is an attribute component in the file structure. That is to say, if your driver supports ioctl, you can use the ioctl function in your program to control the I/O channel of the device.
Ii. Necessity of IOCTL
If you do not need ioctl, you can also control the I/O channel of the device, but that's pretty much the case. For example, we can check whether the data stream with special conventions passes through when implementing write in the driver. If so, then the control command is followed (usually used in socket programming ). However, if this is done, the division of code is unclear, the program structure is chaotic, and the programmer will also be dizzy.
Therefore, we use IOCTL to implement the control function. Remember, what a user program does is to tell the driver what it wants to do by using the command code. As for how to explain these commands and how to implement these commands, this is what the driver wants to do.
Iii. How to Implement IOCTL
This is a very troublesome problem. I can save it. To be clear about it, it cannot be 4000 or 5000 words, so it is impossible for me to make it very clear here, however, if you are interested in how your program is connected with the driver, you can refer to the write mystery I wrote a while ago. The reader only needs to replace write with IOCTL to know how the ioctl of the user program is associated with the ioctl implementation in the driver.
I would like to give a rough idea here, because I think the book "Linux Device Driver" has already been very clear, but it will take some time to look at it.
In the ioctl function implemented in the driver, there is actually a switch {Case} structure. Each case corresponds to a command code and some operations are performed accordingly. How to implement these operations is a task of every programmer, because the devices are specific and cannot be said here. The key is how to organize the command code, because the command code in IOCTL is the only way to contact the user program command and driver support.
The organization of the command code is somewhat exquisite, because we must make sure that commands correspond to devices one by one so that we will not send the correct commands to wrong devices, or send the wrong command to the correct device or the wrong command to the wrong device. These errors will lead to unexpected events. When the programmer finds these strange things, it is very difficult to debug the program to find the errors. Therefore, the Linux core defines a command code as follows:
____________________________________
| Device type | serial number | direction | data size |
| ---------- | -------- | ------ | -------- |
| 8 bit | 8 bit | 2 bit | 8 ~ 14 bit |
| ---------- | -------- | ------ | -------- |
In this way, a command is converted into an order code in the integer form. However, the command code is not intuitive, so some macros are provided in Linux kernel. These macros can generate the command code based on strings that are easy to understand, you can also get some strings that you can understand from the command to indicate the device type, device serial number, data transmission direction, and data transmission size of the command.
I will not explain these macros here. For the specific form, please check the sum in the Linux core source code. The complete definition of these macros is included in the file. Here I will only talk about one thing, that is, "magic number ".
The magic number is a letter and the data length is also 8. Therefore, a specific letter is used to indicate the device type. This is the same as a number, but it is more conducive to memory and understanding. That's it. It's no more complicated.
I have never said more. Let's take a look at the source code. We recommend that you read the example of short in the source code of Linux driver, because it is short and has simple functions, you can understand the functions and details of IOCTL.
Iv. How to obtain the CMD Parameter
The cmd parameter is generated by some macros on the user program based on the device type, serial number, transmission direction, and data size. This integer is passed to the driver in the kernel through system calls, then, the driver uses the decoder macro to obtain the device type, serial number, transmission direction, data size, and other information from this integer, and then performs corresponding operations through the switch {Case} structure.
To thoroughly understand the source code, I can only read the source code. This article is actually just an introduction. The structure of the CMD parameter is still complicated. I think it takes a lot of time to get familiar with it, but it is worth it. The most difficult part of the driver is the understanding of interruption.
V. Summary
IOCTL has nothing to understand. The key is to understand how the CMD command code is generated in the user program and parsed in the driver, the most important workload of programmers is in the switch {Case} structure, because the I/O Control of devices is implemented through this part of code.
Let's list a set of Requests supported by IOCTL. There are a lot of content...