How to implement ioctl function in Linux system?

  

The ioctl function is mainly used to control I/O devices. It can implement the common method of user space to exchange data with the kernel. So what are the functions of the ioctl function under Linux? The following small series will introduce you to the specific usage of the ioctl function under Linux.

Linux kernel concept

Linux is the most popular free computer operating system kernel. It is a Unix-like operating system written in C and conforming to the POSIX standard. Linux was first developed by Finnish hacker Linus Torvalds to try to provide a free and free Unix-like operating system on the Intel x86 architecture. The program began in 1991 with assistance from Minix hackers early in the program, and today countless programmers around the world are helping the program free of charge. Technically speaking, Linux is a kernel. "kernel" refers to a system software that provides hardware abstraction layer, disk and file system control, multitasking and more. A kernel is not a complete operating system. A complete operating system based on the Linux kernel is called the Linux operating system, or GNU/Linux.

The ioctl function is in the driver, because I don't know if there are other occasions where ioctl is used, so the scope of our discussion is specified. Why do you want to write an article? It is because I was confused by ioctl a while ago. I only figured it out in a few days, so I cleaned my mind here.

First, what is ioctl.

The ioctl is a function in the device driver that manages the device's I/O channels. The so-called I /O channel management is to control some of the characteristics of the device, such as the transmission baud rate of the serial port, the speed of the motor and so on. The number of calls is as follows:

int ioctl(int fd, ind cmd, …);

where fd is the file identifier returned by the open function when the user program opens the device, cmd It is the control command of the user program to the device. As for the following ellipsis, it is some supplementary parameters, generally one at most, with or without the meaning of cmd.

The ioctl function is a property component in the file structure. That is, if your driver provides support for ioctl, the user can use the ioctl function in the user program to control the I/O channel of the device.

Second, the necessity of ioctl

If you do not need ioctl, you can also achieve control of the device I /O channel, but that is quite screwed. For example, we can check if there is a special contracted data flow when implementing write in the driver, if any, then follow the control command (usually done in socket programming). However, if you do this, it will lead to an unknown code division, a confusing program, and the programmer will be dizzy.

So, we use ioctl to implement the control function. Keep in mind that what the user program does is tell the driver what it wants to do with the command code. As for how to interpret these commands and how to implement them, this is what the driver does.

Third, how to achieve ioctl

This is a very troublesome problem, I can save the province. To make it clear, no four or five thousand words can't be done, so I can't make it very clear here, but if readers are interested in how the user program is related to the driver, you can see me before. The "Mystery of Write" written by the audience. The reader simply replaces write with ioctl and knows how the ioctl of the user program is associated with the ioctl implementation in the driver.

I am here to say a general idea, because I think the book "Linux Device Drivers" has been very clear, but it will take some time to look at it.

In the body of the ioctl function implemented in the driver, there is actually a switch {case} structure, each case corresponds to a command code, to do some corresponding operations. How to achieve these operations, this is the programmer's own business, because the equipment is specific, there is no way to say. The key is how to organize the command code, because the command code in ioctl is the only way to contact user program commands and driver support.

The organization of the command code is somewhat exquisite, because we must do a one-to-one correspondence between the command and the device, so that the correct command will not be sent to the wrong device, or the error will be The command is sent to the correct device, or the wrong command is sent to the wrong device. These errors can lead to unpredictable things, and when the programmer finds these strange things, it is very difficult to debug the program to find the error.

So in the Linux kernel, define a command code like this:

____________________________________

|  Equipment type |  Serial number |  Direction Data size|

| ----------| --------| ------| --------|

|  8 bit |  8 bit | 2 bit | 8~14 bit|

| ----------| --------| ------| --------|

In this way, a command becomes an integer form of command code. But the command code is very unintuitive, so the Linux Kernel provides macros that generate command codes based on easy-to-understand strings, or get some user-understandable strings from the command code to indicate the device corresponding to the command. Type, device serial number, data transfer direction, and data transfer size.

I won't explain these macros here. The specific form asks the reader to look at the sum of the Linux kernel source code. The files are given a complete definition of these macros. Here I only say one more place, that is, "magic number”.

The magic number is a letter, and the data length is also 8, so a specific letter is used to indicate the device type. This is the same as using a number, but it is more conducive to memory and understanding. That's it, no more complicated.

More to say, the reader still looks at the source code, I recommend you read the short example in the source code of "Linux Device Driver", because it is relatively short, the function is relatively simple, You can see the functions and details of ioctl.

Fourth, how to get the cmd parameter

It is true to say that the cmd parameter is generated by the macro on the user program side according to the device type, serial number, transmission direction, data size, etc. This integer is passed to the driver in the kernel through the system call, and then the driver uses the decoding macro to get the device type, serial number, transfer direction, data size and other information from the integer, and then through the switch{case} structure. operating.

To understand thoroughly, I can only read the source code. My article is actually just a primer. The organization of Cmd parameters is still quite complicated. I think it takes a lot of time to get familiar with it, but it is worthwhile. The hardest part of the driver is the understanding of interrupts.

There is really no hard thing to understand in ioctl. 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 the programmer is in switch{case}. In the structure, because the I/O control of the device is implemented by this part of the code.

The above is the usage of the ioctl function under Linux. The ioctl is mainly used in the driver. It is used to send control and configuration commands to the device. Have you learned it?

Copyright © Windows knowledge All Rights Reserved