在自定义模块中调用sock_release()之后内核被卡住了

时间:2014-08-28 15:09:09

标签: sockets linux-kernel kernel-module

我编写了一个处理基于套接字的TCP连接的内核模块。除了一个特定的用例外,一切都很好用。如果有人建议我如何解决下面描述的问题,我将不胜感激。

我有:

  1. 内核模块,它是使用注册的设备 的 misc_register ()。
  2. 使用标准文件i / o函数与此模块通信的用户空间应用程序:打开关闭 ioctl
  3. 具体情况如下:

    1. 使用insmod加载模块。
    2. 使用标准打开()函数
    3. 从用户应用程序打开关联的设备
    4. 调用 ioctl (),在内核模块中执行以下操作(省略无效代码行):
    5. `

      ...
      sock_create(PF_INET, SOCK_STREAM, 0, sock);
      ...
      flags = O_NONBLOCK;
      sock_map_fd(*sock, flags);
      ...
      kernel_connect (sock, (struct sockaddr *)server_addr, sizeof(struct sockaddr_in), sock->file->f_flags);
      ...
      

      `

      所有功能均成功返回。 TCP连接已成功建立。在此之后,tere也可以在此连接上进行读/写,但它不会影响问题。

      如果应用程序自然结束或者我通过发送SIGINT来中断它,那么很好地关闭连接 - 使用FIN交换等。在SIGKILL上它会按照我的预期发出TCP。到目前为止没问题。

      现在我想关闭这个套接字而没有停止应用程序。我尝试通过另一个ioctl调用在我的内核模块中调用 sock_release ()来实现。在此调用时,TCP连接也很好地关闭。但是现在,当我的应用程序完成或被中断时,内核会卡住!

      我怀疑内核在某种程度上并未“通知”套接字已关闭。它会尝试再次关闭它,并在取消分配套接字内存结构后失败。

      有人使用内核模块的套接字并遇到类似的问题吗? 你能推荐一种替代方法来处理来自内核模块的TCP套接字吗? 从内核中关闭套接字的其他方法是什么?

      非常感谢你。

1 个答案:

答案 0 :(得分:1)

在内核代码调查之后,我发现如果使用 sock_map_fd ()函数将套接字映射到文件,则调用 sock_release ()是不够的。此函数不释放与套接字关联的文件描述符。如果您确实需要将内核套接字映射到文件,请保留 sock_map_fd ()返回的文件描述符,并使用 sys_close ()函数关闭套接字并清理相关文件。请注意,当关闭设备文件描述符时,模块中创建并与文件关联的所有套接字也会自动关闭。

或者,您可以避免将套接字映射到文件描述符。即使没有映射,套接字基本功能也会保持正常。在这种情况下, sock_release ()完美无缺。