配置命令如何从用户空间传递到driver
关于配置命令如何从用户空间传递到driver中,最常用的是使用ioctl.
1. ioctl + socket
2. Ioctl + 文件
在此处以ifconfig wlan0 up为例,来概括下,有些没有理解的东西后续继续补充。
在net-tools中关于ifconfig的调用可以描述如下:
int main(int argc, char** argv)
{
struct ifreq ifr;
skfd = sockets_open(0);
对sockets_open中针对ifconfig做的事情可以简化如下:
skfd = socket(AF_INET, type, 0);
safe_strncpy(ifr.ifr_name, “wlan0”, IFNAMSIZ);
set_flag(ifr.ifr_name, (IFF_UP | IFF_RUNNING))
static int set_flag(char *ifname, short flag)
{
struct ifreq ifr;
safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
ioctl(skfd, SIOCGIFFLAGS, &ifr)
safe_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
ifr.ifr_flags |= flag;
ioctl(skfd, SIOCSIFFLAGS, &ifr) < 0
return (0);
}
}
其实在上述代码中最重要的就是创建一个socket,并用ioctl对这个socket进行操作。
通过调用socket函数,实际上是创建并打开了一个socket,而与该socket相关的文件描述符为socket_file_ops,因此对ioctl(skfd, SIOCGIFFLAGS, &ifr)进行调用是,会调用至内核中的
.unlocked_ioctl.,即sock_ioctl(socket.c) -> inet_ioctl(af_inet.c) -> dev_ioctl(net/core/dev.c)
static const struct file_operations socket_file_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.aio_read = sock_aio_read,
.aio_write = sock_aio_write,
.poll = sock_poll,
.unlocked_ioctl = sock_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_sock_ioctl,
#endif
.mmap = sock_mmap,
.open = sock_no_open, /* special open code to disallow open via /proc */
.release = sock_close,
.fasync = sock_fasync,
.sendpage = sock_sendpage,
.splice_write = generic_splice_sendpage,
.splice_read = sock_splice_read,
};
值得注意的一点是,针对所有的net_device,会有两张hash表来记录信息,一张是依据名字建立的hash表,另外一张是依据ifindex建立的hash表。而在dev_ioctl操作的时候,会首先依据命令行中给的名字wlan0来找到对应的net_device,然后该net_device会一步一步调用的驱动。
另外一种方法还没有整理,这个有空学习整理下再补充。看来源码还是最好的学习工具啊。