读书人

内核模块中异常调用kernel_thread创建

发布时间: 2013-01-25 15:55:29 作者: rapoo

内核模块中错误调用kernel_thread创建内核线程导致模块无法卸载

先介绍一下创建线程的大致流程:在模块的初始化函数中,调用netlink_kernel_create来注册自己的netlink协议,然后返回,接收netlink消息的函数为fcluster_netlink_recv,真正的初始化操作是在接收到netlink报文后才做,创建线程的操作也是在fcluster_netlink_recv中,如下图所示:

内核模块中异常调用kernel_thread创建内核线程导致模块无法卸载

调用kernel_thread的语句为:



在这个流程中并没有对模块引用计数加1的操作,可以判断出在调用netlink_sendmsg之前模块的引用计数已经为1了,那只能是在用户层创建套接字的时候了,看看netlink_create函数,果然是在这个函数中,部分代码如下:


下面是内核模块无法卸载时的情况:

内核模块中异常调用kernel_thread创建内核线程导致模块无法卸载

从两个图中可以看出,无法卸载时最后多了一个sock类型的一行。怎么解决这个问题呢?要么是在新创建的内核线程中关闭所有的打开的文件,要么是在创建内核线程时指定CLONE_FILES标志,或者在内核线程的处理函数中调用daemonize函数
  • #define CLONE_FILES 0x00000400 /* set if open files shared between processes */至于为什么调用kernel_thread时指定CLONE_FILES可以解决这个问题,参见copy_files函数。
    解决这个问题我也花了不少时间,但是通过这个过程,了解了模块的加载过程,netlink报文的发送和接收、及netlink套接字的创建、内核线程的创建等,所以还是受益匪浅啊。等有时间了,我会把load_module、netlink相关的分析整理一下,贴上来,跟大家分享一下。这个问题要描述的话很绕,很难说清。所以如果有什么疑问的话,可以交流一下。

  • 读书人网 >软件开发

    热点推荐