五、调用实践
此处介绍通过自己编写控制程序,在用户空间调用ioctl函数控制内核显示一行信息的例子供大家参考:
1.编写运行于用户空间的控制程序
(1)一般先定义自己的结构参数类型,如下:
typedef struct stMyIoctlArg {
unsigned int cmd;//其实就是第一个参数,当作自己的命令参数
unsigned int arg1; //用于提供给具体的命令参数
unsigned int arg2;
…//如果有更多参数直接加在后面
} IOCTL_ARG,P IOCTL_ARG;
(2)然后在main中赋值并调用ioctl函数:
#define FIOCSMYSHOW 0x1234
int main( int argc, char **argv )
{
int fd;
IOCTL_ARG arg; //需要组织传递到内核的参数
arg.cmd= FIOCSMYSHOW //自定义命令
…//其它参数赋值
int fd = socket( AF_INET, SOCK_STREAM, 0 );//创建控制socket
if ( fd < 0 )
{
perror( "socket failed" );
return 0;
}
if ( ioctl( fd, SIOCSIFBR, &arg) < 0 ) //通过网桥请求参数来控制内核作相关操作
{
perror( "ioctl( SIOCSIFBR ) failed" );
close( fd );
return 0;
}
…
close(fd);
…
}
例子源代码:
2.内核功能支持
2.1、修改内核相关代码:
(1)在内核include/linux/sockios.h的尾部加入前面定义的公共的结构与常量:
typedef struct stMyIoctlArg {
unsigned int cmd;//其实就是第一个参数,当作自己的命令参数
unsigned int arg1;
unsigned int arg2;
…//如果有更多参数直接加在后面
} IOCTL_ARG,P IOCTL_ARG;
#define FIOCSMYSHOW 0x1234
(2)在inet_ioctl函数网桥处理分支处增加如下蓝色字体内容:
IOCTL_ARG myarg;//在inet_ioctl函数开始时加入此变量定义
…
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
if ( copy_from_user( & myarg, (void *) arg, sizeof(IOCTL_ARG ) ) ) //拷贝用户空间参数
return -EFAULT;
switch (myarg.cmd ){
case FIOCSMYSHOW ://解析自己的命令
printk(KERN_INFO “get ioctl hook.\n”); //可以增加对arg1/arg2等参数的解析处理
return 0; //直接返回
break;
…
default:
break;
}
#ifdef CONFIG_KMOD
if (br_ioctl_hook == NULL)
request_module("bridge");
#endif
if (br_ioctl_hook != NULL)
return br_ioctl_hook(arg);
#endif
内核修改文件: 。注意在修改内核代码后,用README中的命令编译一下修改的文件,没有错误才编译内核,避免走弯路重新编译。
2.2、编译内核
具体编译过程请参照网络上的文章,我所用到的重要的命令有:
make mrproper
make oldconfig
make xconfig //在network options中选择802.1 ethernet bridge选项支持网桥功能
make dep
make bzImage
make modules
make modules_install
depmod -a
cp System.map /boot/System.map-2.4.20-8custom
cp arch/i386/boot/bzImage /boot/vmlinuz-2.4.20-8custom
new-kernel-pkg --install --mkinitrd --depmod 2.4.20-8custom
3.运行控制程序
内核编译前运行显示:
内核编译后运行显示:
4.查看结果
可以通过dmesg | grep hook命令查看结果,显示:
这正是我们在内核中要打印的字符,说明我们的控制命令已经通知给内核了。
六、结束语
ioctl系统调用是最常用的用户与内核空间交互的手段之一,linux系统自带的相当多的命令工具尤其是网络控制工具都是采用ioctl控制框架实现了用户和内核通信的桥梁,在当前一些基于内核模块技术的软件系统中也有重要的用途,如某些宽带计费网关、防火墙软件、网络交换机等。了解ioctl控制框架,无疑会提高我们对linux内核通信机制的认识,也可以指导我们的实践工作。
七、参考资料
1 linux内核源代码情景分析
2 linux内核2.4.0源码
3 ioctl man手册
4 ifconfig工具源码
本文转自:http://blog.csdn.net/jccz_zys/archive/2006/12/05/1431017.aspx
作者:松哥 email:jccz_zys@tom.com MSN: jccz_zys@163.net