Linux Kernel ioctl function learning

Source: Internet
Author: User
Tags posix

From: http://bbs.chinaunix.net/forum.php? MoD = viewthread & tid = 1967512.


Detailed description of ioctl function parameters

Ioctl function
This function affects an open file referenced by the FD parameter.
# Include
Int IOCTL (int fd, int request,.../* void * Arg */);
Return 0: Success-1: Error
The third parameter is always a pointer, but the pointer type depends on the request parameter.
We can divide network-related requests into 6 categories:
Set interface operations
File Operations
Interface operation
ARP high-speed cache operations
Route table operations
Stream System
The following table lists the Request Parameters for network-related IOCTL requests and the data types that the ARG address must point:
Type request description Data Type
Set Interface
Siocatmark
Siocspgrp
Siocgpgrp
Whether it is in the out-of-band mark
Set the process ID or process group ID of the Set Interface
Obtain the process ID or group ID of the Set interface.
Int
Int
Int
File
Fionbin
Fioasync
Fionread
Fiosetown
Fiogetown
Set/clear non-blocking I/O flag
Set/clear signal-driven asynchronous I/O flag
Obtain the number of bytes in the receiving cache.
Set the process ID or group ID of the file.
Obtain the process ID or group ID of the file.
Int
Int
Int
Int
Int
Interface
Siocgifconf
Siocsifaddr
Siocgifaddr
Siocsifflags
Siocgifflags
Siocsifdstaddr
Siocgifdstaddr
Siocgifbrdaddr
Siocsifbrdaddr
Siocgifnetmask
Siocsifnetmask
Siocgifmetric
Siocsifmetric
Siocgifmtu
Siocxxx
Retrieve the list of all interfaces
Set the interface address
Obtain the interface address
Set interface flag
Get interface flag
Set point-to-point address
Get point-to-point address
Get broadcast address
Set broadcast address
Obtain Subnet Mask
Set Subnet Mask
Obtain the measure of an interface
Set the measure of the interface
Obtain the MTU Interface
(A lot more depends on the implementation of the system)
Struct ifconf
Struct ifreq
Struct ifreq
Struct ifreq
Struct ifreq
Struct ifreq
Struct ifreq
Struct ifreq
Struct ifreq
Struct ifreq
Struct ifreq
Struct ifreq
Struct ifreq
Struct ifreq
ARP
Siocsarp
Siocgarp
Siocdarp
Create/modify ARP table items
Obtain ARP table items
Delete ARP table items
Struct arpreq
Struct arpreq
Struct arpreq
Routing
Siocaddrt
Siocdelrt
Add path
Delete path
Struct rtentry
Struct rtentry
Stream
I _xxx
Set operation:
There are three IOCTL requests explicitly used to set interface operations. Both require that the third parameter of IOCTL be a pointer to an integer.
Siocatmark: If the degree pointer of this set of interfaces is currently in the out-of-band mark, a non-0 value is returned through the integer pointed to by the third parameter; otherwise, a 0 value is returned. POSIX replaces this request with the sockatmark function.
Siocgpgrp: return the process ID or group ID of this interface through the integer indicated by the third parameter. This ID specifies the receiving process of the sigio or sigurg signal of this interface. This request is equivalent to the f_getown command of fcntl. POSIX standardizes the fcntl function.
Siocspgrp: sets the process ID or group ID of this interface to the integer pointed to by the third parameter. This ID specifies the receiving process of the sigio or sigurg signal of this interface, this request is equivalent to the f_setown command of fcntl. POSIX standardizes fcntl operations.
File Operations:
The following five requests require the third parameter of IOCTL to point to an integer.
Fionbio: Based on the third parameter of ioctl, point to a 0 or non-0 value to clear or set the non-blocking flag of this interface. This request is equivalent to the o_nonblock File status flag, which is cleared or set through the f_setfl command of fcntl.
Fioasync: Based on the third parameter of iocl, point to a 0 value or a non-0 value to clear or set the signal-driven asynchronous I/O flag for this interface, respectively, it determines whether to receive asynchronous I/O signals (sigio) for this interface ). This request is equivalent to the o_async File status flag, which can be cleared or set through the f_setfl command of fcntl.
Fionread: returns the number of bytes in the buffer zone currently received by this interface through the integer pointed to by the third parameter of IOCTL. This feature is also applicable to files, pipelines, and terminals.
Fiosetown: equivalent to siocspgrp for the set interface.
Fiogetown: equivalent to siocgpgrp for the set interface.
Interface Configuration:
All the interfaces in the system are completed by the siocgifconf request. The request uses the ifconf structure, and the ifconf uses the ifreq
Structure:
Struct ifconf {
Int ifc_len; // buffer size
Union {
Caddr_t ifcu_buf; // input from user-> kernel
Struct ifreq * ifcu_req; // return of structures returned
} Ifc_ifcu;
};
# Define ifc_buf ifc_ifcu.ifcu_buf // buffer address
# Define ifc_req ifc_ifcu.ifcu_req // array of structures returned
# Define ifnamsiz 16
Struct ifreq {
Char ifr_name [ifnamsiz]; // Interface Name, e.g., "le0"
Union {
Struct sockaddr ifru_addr;
Struct sockaddr ifru_dstaddr;
Struct sockaddr ifru_broadaddr;
Short ifru_flags;
Int ifru_metric;
Caddr_t ifru_data;
} Ifr_ifru;
};
# Define ifr_addr ifr_ifru.ifru_addr // address
# Define ifr_dstaddr ifr_ifru.ifru_dstaddr // otner end of p-to-P Link
# Define ifr_broadaddr ifr_ifru.ifru_broadaddr // broadcast address
# Define ifr_flags ifr_ifru.ifru_flags // flags
# Define ifr_metric ifr_ifru.ifru_metric // Metric
# Define ifr_data ifr_ifru.ifru_data // for use by Interface
Before calling ioctl, we must first split a buffer zone and an ifconf structure before initializing the latter. For example
Shows the initialization structure of an ifconf structure, where the buffer size is 1024, and the third parameter of IOCTL points
Such an ifconf structure.
Ifc_len
Ifc_buf
1024
---------------------> Cache
Assume that the kernel returns two ifreq structures. When IOCTL returns, the two ifreq structures are entered in the buffer zone of the same ifconf structure. The ifc_len members of the ifconf structure are also updated, to reflect the amount of information stored in the buffer
Generally, the call of IOCTL in a user program is:
IOCTL (int fd, int command, (char *) argstruct)
IOCTL calls are related to network programming (this article only discusses this). The file descriptor FD is actually returned by the socket () System Call. The value of the command parameter is specified by/usr/include/Linux/sockios. h. Different functions of these commands can be divided into the following sub-classes:
• Change the route table (for example, siocaddrt and siocdelrt ),
• Read/update arp/RARP caches (for example, siocdarp and siocsrarp ),
• Generally related to network interfaces (such as siocgifname and siocsifaddr)
There are various examples in the gooodies directory that show how to use IOCTL. When you look at these programs, note that the argstruct parameter is related to the command parameter. For example, IOCTL related to the route table uses the rtentry structure. rtentry is defined in/usr/include/Linux/route. H (see the example adddefault. C ). ARP-related IOCTL calls use the arpreq structure. arpreq is defined in/usr/include/Linux/if_arp.h (see the example of arpread. C)
The command parameter used for IOCTL calls related to network interfaces usually looks in the form of siocxifyyyy. Here, X is either S (set, write) or G (get, read ). In the getifinfo. C program, command parameters in this form are used to read IP addresses, hardware addresses, broadcast addresses, and flag related to network interfaces ). In these IOCTL calls, the third parameter is the ifreq structure, which is defined in/usr/include/Linux/If. h. In some cases, the ioctrl call may be performed on sockios. for example, the wavelan wireless network card stores information about the signal strength of the wireless network.
Can be used. But how do users get this information? Our first instinct is to define new ioctl commands in sockios. H, such as siocgifwvlnss (which stands for wavelan signal strength ). However, unfortunately, this command is not meaningful to all other network interfaces (such as loopback) and should not be allowed to use IOCTL commands for network interfaces other than the wavlan card. So what we need is a mechanism that can define an IOCTL command related to network interfaces. Fortunately, a hook mechanism has been built into the Linux operating system for this purpose. When you read the sockios. h file again, you will find that each device has been pre-defined
IOCTL command of siocdevprivate. However, its implementation will be left to those who develop the corresponding driver.
Generally, a user program uses IOCTL (sockid, siocdevprivate, (char *) & IFR) to call IOCTL commands related to a certain device (a special device like wavelan, IFR is a variable in the form of struct ifreq IFR. The user program should fill in the IFR. ifr_name with the name related to the device. For example, assume that the interface number used by wavelan is eth1. Generally, a user program also needs to exchange the command parameters and results of IOCTL with the kernel. This can be achieved through IFR. ifr_data is implemented. For example, if you want to obtain information about the signal strength in wavelan, you can return this variable. The source code of Linux includes de4x5 and ewrk3, which define and implement specific IOCTL.
Call. The source code of these two devices is in de4x5. H, de4x5. C, ewrk3.h, and ewrk3.c (in the/usr/src/Linux/Drivers/NET/directory ). Both devices define their own structures (struct ewrk3_ioctl and struct de4x5_ioctl) to facilitate information exchange between user programs and device drivers. Before each call to ioctl, the user program should set an appropriate initial value in the corresponding structure variable and point IFR. ifr_data to this value.
Before we further discuss the code of ewrk3 and de4x5, let's take a closer look at how IOCTL calls are implemented step by step. All interface-related IOCTL requests (siocxifyyyy and siocdevprivate) will call dev_ioctl () (in/usr/src/Linux/NET/CORE/dev. C ). But this is only a wrapper, and the actual action will be implemented by dev_ifsioc () (also in Dev. C. Almost all the work done by the dev_ioctl () function is to check whether the call has proper permissions (for example, the root permission is required to change the route table ). The dev_ifsioc () function first includes
The structure of the device that matches IFR. ifr_name (defined in/usr/include/Linux/netdevice. h ). However, this is after implementing specific interface commands (for example, siocgifaddr. These specific interface commands are placed in a large switch statement. The siocdevprivate command and other code between 0x89f0 and 0x89ff will appear in a branch-default statement in the switch statement. The kernel checks whether a device-related IOCTL handle (handler) is defined in the structure variable of the device ). The handle here is a function pointer that represents the do_ioctl part of the device's structural variable. If you have already set this sentence
Then the kernel will execute it.
Therefore, to implement a device-related IOCTL command, all you need to do is write an IOCTL handle related to the device, the do_ioctl part of the device's Structure Variable points to the handle. For the ewrk3 device, its handle is ewrk3_ioctl () (IN ewrk3.c) and the corresponding structure variables that indicate the device are initialized by ewrk3_init. In the ewrk3_ioctl () code, it is clearly pointed out that IFR. ifr_data is used to exchange information between the device driver and the user program. Note that this part of memory can communicate information in two directions. For example, in the driver code of ewrk3, the first two bytes of if. ifr_data are used to represent special actions (for example
For example, ewrk3_set_prom, ewrk3_clr_prom), and this action meets the user's requirements (the driver implements multiple device-related commands called by siocdevprivate. In addition, the buffer to which 5th bytes point in IFR. ifr_data is used to exchange other information (for example, when ewrk3_set_hwaddr and ewrk3_get_hwaddr are used)
When you go deep into ewrk3_ioctl (), note that the next user process cannot directly access the memory of the kernel. Therefore, the driver developer can use two special functions: memcpy_tofs () and memcpy_fromfs (). The kernel function memcpy_tofs (arg1, arg2, arg3) Copies arg3 bytes from the address arg2 (user space) to the address arg1 (kernel space. Similarly, memcpy_fromfs (arg1, arg2, arg3) Copies arg3 bytes from the address arg2 (user space) to the address arg1 (kernel space. Before these calls, verify_area () will check whether the process has proper access
Limits. In addition, use the printk () function to output debug information. This function is similar to the printf () function, but cannot process the number of floating point types. Kernel code cannot use the printf () function. The result of the printk () function is recorded in/usr/ADM/messages. For more information about these functions, see the supporting functions section in the Linux kernel hacker's Guide (on the homepage of the Linux documentation website.

Linux Kernel IOCTL Functions
Trangod was released on |
4744 times read font size:
Large

Medium

Small
(3 comments from netizens)
I want to comment

Generally, IOCTL is called as follows: IOCTL (int fd, int command, (char *) argstruct) has network-related code, therefore, the file description symbol FD is returned by the socket () system call, and the command parameter can be/usr/include/Linux/sockios. h. In the header file, these commands are divided into multiple types based on the aspects involved in the issues it can solve.
For example:
Change the route table (siocaddrt, siocdelrt)
  
Read or update arp/RARP cache (siocdarp, siocsrarp)
General network-related functions (siocgifname, siocsifaddr, etc)
The goodies directory contains many sample programs that demonstrate IOCTL usage. When you look at these programs, learn the specific call parameter structure based on the ioctl command type. For example: the IOCTL related to the route table uses the rtentry structure. The rtentry structure is defined in/usr/include/Linux/route. in the H file, the arpreq structure used for the ARP-related IOCTL call is defined in the/usr/include/Linux/if_arp.h file. the most representative characteristics of IOCTL commands related to network interfaces are that they all start with S or g, which is actually to set or get data, getifinfo. C program uses these commands to read IP address information, hardware address information, broadcast address information, and network interface-related flags. for these ioctl, the third parameter is an ifreq struct, which is defined in/usr/include/Linux/if. in the header file H, in some cases, the new IOCTL command may be needed (except for the one defined in the header file), such
The wavelan wireless network card maintains the signal strength information, which may be useful to user programs. How does a user program access this information? Our first response is to define a new command in sockios. in the header file H, for example, siocgifwvlnss, unfortunately, this command is meaningless on other network interfaces, in addition, we try to use this name on other interfaces, instead of using it on the wireless network port for illegal access. What we need is to define the Mechanism of New Interface commands. Fortunately, the Linux operating system has built-in hooks for this purpose. If you look at the header file sockios. h. You will notice that every device has a predefined siocdevprivate command, and the task of implementing it will be handed over to the programmer who writes the device driver. according to the General Convention, a user program calls a specific IOCTL command as follows:
IOCTL (sockid, siocdevprivate, (char *) & IFR) IFR is an ifreq struct variable. It fills the IFR Name field of IFR with the interface name associated with the device, for example, the aforementioned Wireless Network Interface Name Is eth1.
Without losing its universality, a user program will also need to exchange command parameters and operation results with the kernel, and these have passed through a domain IFR. ifr_data is filled. For example, the signal strength of the ENI is returned to this domain. The Linux Source Code contains two special devices de4x5 and ewrk3. They define and implement special IOCTL commands ., the source code of these devices is in the following file: de4x5. h, de4x5. c, ewrk3.h, and ewrk3.c. Both of them define their own private structure for data exchange between the user space and the driver. Before ioctl, the user program fills in the required data and changes the IFR. ifr_data points to this struct.
Before entering the code, let's track several steps for processing the ioctl system call. All IOCTL requests of interface types lead to dev_ioctl () called. This IOCTL is only a package, and most of the actual operations are left to dev_ifsioc ()., the only thing that dev_ioctl () needs to do is to check whether the call process has a suitable license to issue the command. Then, one of the first things that dev_ifsioc () needs to do is to get and name the domain IFR. the device structure corresponding to ifr_name is implemented after a large switch block code.
The siocdevprivate command and the siocdevprivate + 15 command parameters are all handed over to the default operation. These are switch branch statements. what happens here is that the kernel checks whether a special IOCTL callback of a device has been set in the device structure, which is a function pointer maintained in the device structure. If the callback has been set, the kernel will call it.
Therefore, to implement a special ioctl, you need to write a callback for a special ioctl, and then let the do_ioctl domain in the device structure point to it. For ewk3 devices, this function is called ewrk3_ioctl (). The device structure is initialized in ewrk3_init (). The Code of ewrk3_ioctl () clearly shows IFR. ifr_data is used to exchange information between user programs and drivers. Note that this area of the memory serves to exchange data in two directions. For example, in the ewrk3 driver code, IFR. the first two bytes of ifr_data are used to pass the desired action to the driver. The buffer to which the fifth byte points is used to exchange other information.
When you browse the ewrk3_ioctl () code, remember that in an application, user space commands cannot access the kernel space. For this reason, two special steps are provided to the driver writer. they are memcpy_tofs () and memcpy_fromfs (). In the kernel, we use memcpy_tofs () to copy the kernel data to the user space. Similar to memcpy_fromfs (), we only copy the user data to the kernel space .. These program steps are executed because verify_area () is called to ensure that data access is not illegal. Similarly, remember that printk () is used to print debugging information. This function is very similar to printf (), but it cannot process floating point data. printf () functions cannot be used in the kernel. The output generated by printk () is dumped to a directory./usr/ADM/messages.
IOCTL (reproduced)

To select the ioctl number for the driver as agreed in the Linux kernel, you should first look at the include/ASM/IOCTL. h and documentation/ioctl-number.txt files.
_ IO (type, NR)
Used to construct a command number without parameters;
_ Ior (type, NR, datatype)
Command number used to construct the command to read data from the driver;
_ Iow (type, NR, datatype)
Command Used to write data;
_ IOWR (type, NR, datatype)
It is used for bidirectional transmission.
Return Value
----------------------------------
The implementation of IOCTL is usually a switch statement based on command numbers. But what is the default option when the command number cannot match any valid operation? This issue is controversial. Some kernel functions return-ENVAL ("invalid argument, invalid parameter"), which is reasonable because the command parameter is indeed not a valid parameter. However, the POSIX standard specifies that-enotty should be returned if an inappropriate IOCTL command parameter is used. Library C interprets this error code as "inappropriate IOCTL for device, IOCTL for an inappropriate device", which looks more appropriate. Despite this, it is still common to put the invalid IOCTL command back-einval.
CD ioctl_test
Ioctl_test.c
-------------------------------------------
# Include
# Include
# Include
# Include
# Include
# Include
# Include
# Include "ioctl_test.h"
Typedef struct {
Struct class * class;
Int Major;
Char * dev_name;
} Module_data;
Static module_data * g_module;
Static int test_dev_ioctl (struct inode * inode, struct file * file,
Unsigned int cmd, unsigned long Arg)
{
Int ret, Val;
Switch (CMD ){
Case device_read:
{
Return put_user (10, (long *) Arg );
}
Case device_write:
{
Ret = get_user (Val, (long *) Arg );
If (RET)
Return ret;
Printk ("Val = % d \ n", Val );
Break;
}
Default:
Return-enotty;
}
Return 0;
}
Static int test_dev_open (struct inode * inode, struct file * file)
{
Printk ("test_dev open \ n ");
Return 0;
}
Static struct file_operations test_dev_fops = {
IOCTL: test_dev_ioctl,
Open: test_dev_open,
};
Static int _ init test_dev_init (void)
{
Int res;
Struct class_device * temp_class;
Struct class * dev_class;
Int Major;
Char dev_name [] = "test_dev ";
G_module = kmalloc (sizeof (module_data), gfp_kernel );
If (g_module = NULL ){
Perror ("kmalloc error \ n ");
Return-enomem;
}
Memset (g_module, 0, sizeof (module_data ));
Res = register_chrdev (0, dev_name, & test_dev_fops );
If (RES major = major;
G_module-> class = dev_class;
G_module-> dev_name = dev_name;
Return 0;
}
Static void _ exit test_dev_exit (void)
{
Struct class * dev_class;
Int Major;
Char * dev_name;
Dev_class = g_module-> class;
Major = g_module-> Major;
Dev_name = g_module-> dev_name;
Class_device_destroy (dev_class, mkdev (Major, 0 ));
Class_destroy (dev_class );
Unregister_chrdev (Major, dev_name );
Kfree (g_module );
Pinfo ("test_dev driver removed \ n ");
Return;
}
Module_init (test_dev_init );
Module_exit (test_dev_exit );
Module_license ("GPL ");
Ioctl_test.h
-------------------------------------------
# Ifndef mxc_cmb_inno_h
# Define mxc_cmb_inno_h
# UNDEF perror
# Define perror (FMT, argS ...) printk (kern_err "CMB driver error: line % d-% s ():" FMT ,__ line __, _ FUNCTION __, # ARGs)
# UNDEF pinfo
# Define pinfo (FMT, argS...) printk (kern_info FMT, # ARGs)
# UNDEF pdebug/* UNDEF it, just in case */
# Ifdef cmb_inno_debug
# Define pdebug (FMT, argS ...) printk (kern_debug "CMB driver line % d-% s ():" FMT ,__ line __, _ FUNCTION __, # ARGs)
# Else
# Define pdebug (FMT, argS...)/* Not debugging: nothing */
# Endif
# Define device_read _ ior ('T', 1, INT)
# Define device_write _ Iow ('T', 2, INT)
# Endif
Makefile
-------------------------------------------
Kdir =/usr/src/linux-headers-2.6.24-19-generic
OBJ-M + = ioctl_test.o
ALL:
Make-C $ (kdir) M = 'pwd' modules
Clean:
Make-C $ (kdir) M = 'pwd' clean
CD ..
Test_ioctl.c
-------------------------------------------
# Include
# Include
# Include
# Include "ioctl_test/ioctl_test.h"
# Define inno_dev_name "/dev/test_dev"
Int main ()
{
Int FD, RET, get_int, put_int = 527;
FD = open (inno_dev_name, o_rdwr );
Ret = IOCTL (FD, device_read, & get_int );
If (Ret

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.