天天看点

linux kernel ioctl系统调用

Q:用户空间调用ioctl操作网卡设备行为时,调用链是什么样的?不同的socket类型是否也不一样?

先来看一下系统调用ioctl的调用链是什么样的,请看下表

函数名称 文件名 做了什么
SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) fs/ioctl.c ioctl函数入口
do_vfs_ioctl fs/ioctl.c 真正入口,这个函数里边会区分哪些是针对真正的文件进行操作的,哪些是针对虚拟文件进行操作的,显然socket这类的ioctl就属于虚拟文件
vfs_ioctl fs/ioctl.c 这个函数会根据文件描述符的指针找到文件操作指针f_op对应的指针接口函数unlocked_ioctl,那么这个unlocked_ioctl的函数指针在哪里注册的呢?net/socket.c里边调用系统调用socket创建sock文件描述符的时候通过sock_map_fd函数再调用函数sock_alloc_file,这个函数里边会将socket_file_ops注入到socket文件描述符里边,有的人会好奇网卡驱动里边也有关于unlocked_ioctl函数指针的注册,那网卡驱动的ioctl是怎么被调用的呢?网卡驱动的ioctl是先open一个/dev/netdeviceName,然后再调用ioctl传递设备的文件描述符。
sock_ioctl net/socket.c 函数入口则判断输入的cmd命令是否属于[SIOCDEVPRIVATE, SIOCDEVPRIVATE+15]这个区间,如果属于则调用dev_ioctl函数去操作设备驱动相关功能接口进行设置,如果不在这个区间则针对各个cmd进行处理,如果这个函数的cmd都没对应的处理动作,则调用sock_do_ioctl进行处理
sock_do_ioctl net/socket.c 这个函数根据sock->ops调用各自的ioctl指针,这里就是转到各family模块去处理了,比如netlink模块就去调用net/netlink/af_netlink.c下的sock_no_ioctl,pf_packet则调用net/packet/af_packet.c下的packet_ioctl,如果各模块的ioctl函数处理之后返回ENOIOCTLCMD错误即找不到命令,则仍然调用dev_ioctl去处理
dev_ioctl net/core/dev_ioctl.c 这个函数主要针对真实网卡驱动进行设置,比如设置组播接收以及混杂模式等。

有了上面的分析,我们可以回答第二个问题,如果是针对网卡进行的操作,无论通过哪种family类型的socket,就是可以的,但是针对指定family特有的CMD则需要区分。

参考文章: IOCTL in Linux (I/O Control) – Linux Device Driver Tutorial Part 8

继续阅读