论坛交流
首页办公自动化| 网页制作| 平面设计| 动画制作| 数据库开发| 程序设计| 全部视频教程
应用视频: Windows | Word2007 | Excel2007 | PowerPoint2007 | Dreamweaver 8 | Fireworks 8 | Flash 8 | Photoshop cs | CorelDraw 12
编程视频: C语言视频教程 | HTML | Div+Css布局 | Javascript | Access数据库 | Asp | Sql Server数据库Asp.net  | Flash AS
当前位置 > 文字教程 > C语言程序设计教程
Tag:新手,函数,指针,数据类型,对象,Turbo,入门,运算符,数组,结构,二级,,tc,游戏,试题,问答,编译,视频教程

Linux ioctl() Primer

文章类别:C语言程序设计 | 发表日期:2008-9-24 14:37:19

Vipul Gupta

In general an ioctl call in a user program looks like ioctl(int fd, int command, (char *) argstruct). For ioctl calls related to the networking code (these are the only ones we will deal with in this note), the file des criptor fd is actually a socket des criptor returned by the socket() system call. The command could be any one of those listed in /usr/include/linux/sockios.h. These commands are subdivided into a number of categories depending on what aspect of networking they deal with:

changing the routing table (e.g. SIOCADDRT, SIOCDELRT),
reading/updating the ARP/RARP caches (e.g. SIOCDARP, SIOCSRARP),
generic functions related to network interfaces (e.g. SIOCGIFNAME, SIOCSIFADDR etc)
The Goodies directory contains a number of sample programs illustrating the use of networking ioctl calls. As you look at these programs, notice how the structure used for argstruct depends on the ioctl command type. For example, routing table related ioctls use the rtentry structure defined in /usr/include/linux/route.h (see adddefault.c for an example) and ARP related ioctls use the arpreq structure defined in /usr/include/linux/if_arp.h (see arpread.c).

Network interface related ioctl commands typically look like SIOCxIFyyyy where x is either S (set, write) or G (get, read). The getifinfo.c program uses such commands to read the IP address, hardware address, broadcast address and flags associated with a network interface. For these ioctls, the third argument is an ifreq structure which is defined in /usr/include/linux/if.h. In some cases, new ioctl commands may be needed in addition to those defined in sockios.h, e.g. the WaveLAN wireless networking card maintains information about wireless signal strength which may be of use to a user program. How should user programs be allowed access to this information? Our first instinct may be to define a new ioctl command in sockios.h, e.g. SIOCGIFWVLNSS (Get WaVeLaN Signal Strength). Unfortunately, this command makes no sense at all for other interfaces (e.g. loopback) and attempts to use this ioctl command on interfaces other than WaveLAN cards should be disallowed. What we need, then, is a mechanism to define interface specific ioctl commands. Luckily, the Linux OS already has built-in hooks for this purpose. If you look at sockios.h again, you will notice that each device has a predefined SIOCDEVPRIVATE ioctl command. The implementation of this command is left totally upto the person writing the corresponding device driver.

By convention, a user program invokes a device specific ioctl command as ioctl(sockid, SIOCDEVPRIVATE, (char *) &ifr) where ifr is defined as struct ifreq ifr. It fills ifr.ifr_name with the interface name associated with the device, e.g. on tether, the WaveLAN card is named eth1. Typically, a user program will also need to exchange command arguments and results with the kernel and that is done through the ifr.ifr_data field, e.g. the signal strength infromation for the WaveLAN card could be returned in this field. The Linux source code already includes two devices de4x5 and ewrk3 that define and implement device specific ioctl commands. The source code for these drivers is in de4x5.h, de4x5.c, ewrk3.h, ewrk3.c, (in /usr/src/linux/drivers/net/). Both drivers define their own private structures (struct ewrk3_ioctl and struct de4x5_ioctl) for exchanging information between user programs and the drivers. Before the ioctl call, the user program fills out the necessary fields in this structure and points ifr.ifr_data to it.

Before we go any further into the driver code for ewrk3 and de4x5, let us trace through various steps in the processing of an ioctl call. All interface-type ioctl requests (SIOCxIFyyyy and SIOCDEVPRIVATE) result in dev_ioctl() (in /usr/src/linux/net/core/dev.c) being called. This is just a wrapper and most of the real action is left for dev_ifsioc() (also in dev.c). About the only thing dev_ioctl() does is check whether a calling process has the appropriate permissions to issue the command (e.g. commands to alter the routing tables require root permissions). One of the first things dev_ifsioc() does is get the device structre (struct device defined in /usr/include/linux/netdevice.h) corresponding to the device named in ifr.ifr_name. This is followed by the code to implement generic interface commands (e.g. SIOCGIFADDR) inside a giant switch statement. The SIOCDEVPRIVATE command and any others with codes from 0x89F0 through 0x89FF end up in the default: branch for this switch. Here, the kernel checks to see if a device specific ioctl handler has been set up in the device structure. The handler is maintained as a function pointer in the do_ioctl field of the device structure. If the handler has been set, the kernel invokes it.

So, to implement device specific ioctls, all one needs to do is write a device specific ioctl handler and have the do_ioctl field in the corresponding device structure point to it. For the ewrk3 device, this function is called ewrk3_ioctl() (in ewrk3.c) and the corresponding device structure is initialized in ewrk3_init(). The ewrk3_ioctl() code clearly indicates the use of ifr.ifr_data for exchanging information between the device driver and user program. Note that this area of memory can be used for bidirectional information exchange. For example, in the ewrk3 driver code, the first two bytes of ifr.ifr_data are used to convey the specific action (e.g. EWRK3_SET_PROM, EWRK3_CLR_PROM) desired by the user (the driver implements multiple device specific commands that are all invoked through SIOCDEVPRIVATE). Also, and the buffer pointed to by the fifth byte in ifr.ifr_data is used to exchange other information (hardware address when using EWRK3_SET_HWADDR or EWRK3_GET_HWADDR).

As you go through ewrk3_ioctl(), keep in mind that normally a user process cannot directly access kernel memory. For this reason, two special procedures memcpy_tofs() and memcpy_fromfs() are provided to driver writers. The kernel procedure memcpy_tofs(arg1, arg2, arg3) copies arg3 bytes from starting address arg2 (in kernel space) to address arg1 (in user space). Similarly, memcpy_fromfs(arg1, arg2, arg3) copies arg3 bytes from starting address arg2 (in user space) to address arg1 (in kernel space). These procedures are preceded by calls to verify_area() to verify that the process has appropriate access permissions. Also notice the use of the printk() function to print debugging information. This function is similar to printf() but cannot handle floating point. The printf() function is not available to kernel code. The output generated by printk() is logged into /usr/adm/messages. For more information on these and related procedures, look at the section titled Supporting Functions in Michael K. Johnson's "Linux Kernel Hacker's Guide" which is accessible from the Linux Documentation Home Page.
视频教程列表
文章教程搜索
 
C语言程序设计推荐教程
C语言程序设计热门教程
看全部视频教程
购买方式/价格
购买视频教程: 咨询客服
tel:15972130058