其中调用到函数的说明:
★ fget()函数,它是用来获取操作文件的指针,在这篇文档里,我是使用socket创建了一个文件描述符,fd = socket(AF_INET6, SOCK_DGRAM, 0);用户态的创建socket()到内核中传给函数sys_socket()处理, sys_socket()函数先调用函数sock_create()创建socket,然后把socket操作和文件操作关联起来,具体调用函数 sock_map_fd()来实现,成功后将文件描述和文件结构file都保存在sock->file中。
对于函数fget()函数,它首先调用fcheck函数,检查一下文件描述符fd是否对应一个打开的文件,如果是就获取该文件,调用函数get_file()将f_count加1。
具体看一下fcheck函数的执行,参考代码:
|
★ filp->f_op->ioctl()函数,调用设备对应的ioctl函数,对于使用socket创建文件描述符,它应该调用sock_ioctl()函数,具体流程图如下:
每一个设备都可以定义自己的ioctl命令字,命令编号的范围是 SIOCDEVPRIVATE到SIOCDEVPRIVATE + 15。针对ipv6隧道,它定一个四个命令字,分别是SIOCGETTUNNEL,SIOCADDTUNNEL,SIOCCHGTUNNEL, SIOCDELTUNNEL。用户空间通过ioctl系统调用,最终调用到内核中定义的函数ip6ip6_tnl_ioctl。
|
■ sock_ioctl()
功能::直接调用一个协议特定的函数,如:当socket family是PF_INET6,调用函数inet6_ioctl。
■ inet6_ioctl()
功能:v6对应socket的ioctl内核函数,根据不同的case情况,作相应的处理。
|
当ioctl命令字不满足上述各种case情况时:
|
该设备自己定义了一些ioctl命令字范围在SIOCDEVPRIVATE到SIOCDEVPRIVATE + 15之间),调用函数dev_ioctl实现对该设备指定的ioctl命令的操作。
■ dev_ioctl()
功能:用来处理所有设备接口的ioctl请求,只是一个包装器, 实际的动作将由dev_ifsioc()来实现。dev_ioctl做的只是检查这个调用是否具有了正当的权限。
■ dev_ifsioc()
功能:真正处理所有设备接口的ioctl请求。
具体操作说明:函数首先要做的一些事情包括得到与ifr.ifr_name相匹配的设备的结构,但这是在实现特定的接口命令之后。这些特定的接口命令被放置到一个巨大的switch语句之中。其中SIOCDEVPRIVATE命令和其他的在0x89F0到0x89FF之间的代码将出现在switch语句中的一个分支——default语句中,代码最后还增加了对无线网络的支持。内核执行时会检查表示设备的结构变量中,是否已经定义了一个与设备相关的ioctl句柄(handler)。这里的句柄是一个函数指针,它在表示设备的结构变量中 do_ioctl部分。如果已经设置了这个句柄,那么内核将会执行它。如ipv6隧道设备体,在初始化时,就作了说明:dev->do_ioctl = ip6ip6_tnl_ioctl,其中函数ip6ip6_tnl_ioctl就是该设备对应的ioctl句柄,由于隧道设备是自己定义的ioctl命令字,因而执行应在default语句中,进而调用到自己定义的ioctl处理函数ip6ip6_tnl_ioctl。
