c - 在内核中使用 sock_create、accept、bind 等

标签 c linux sockets linux-kernel kernel

我正在尝试将 echo TCP 服务器实现为可加载的内核模块。
我应该使用 sock_create 还是 sock_create_kern?

我应该使用接受还是 kernel_accept?

我的意思是我应该使用 kernel_accept 是有道理的;但我不知道为什么。我不能在内核中使用普通套接字吗?

最佳答案

问题是,您正试图将 user space 应用程序硬塞到 kernel 中。

套接字(和文件等)是内核通过内核用户空间 API/ABI 提供给用户空间应用程序的东西。 一些 ,但不是全部,也有一个内核可调用,用于另一个内核希望使用提供给用户空间的东西的情况。

让我们看看内核源代码中 net/socket.csocket()accept() 系统调用的 Linux 内核实现;寻找 SYSCALL_DEFINE3(socket,SYSCALL_DEFINE3(accept,SYSCALL_DEFINE4(recv, 等。

(我建议您使用例如 Elixir Cross Referencer 在 Linux 内核源代码中查找特定标识符,然后在官方内核 Git 树之一在线查找实际代码;这就是我所做的,无论如何。)

请注意指针参数如何具有 __user 限定符:这意味着指向的数据必须驻留在用户空间中,并且函数最终将使用 copy_from_user()/copy_to_user() 来检索或设置数据。此外,操作访问文件描述符表,它是进程上下文的一部分:通常只存在于用户空间进程的东西。

本质上,这意味着您的内核模块必须创建一个用户空间“进程”(足以满足使用内核接口(interface)时跨越用户空间-内核边界的要求)以至少“保存”内存和文件描述符。这是很多工作,最终,它不会比用户空间应用程序的性能更高。 (Linux 内核开发人员已经为此工作了数十年。有一些专有操作系统在“内核空间”中做事可能更快,但在 Linux 中并非如此。在用户空间做事的成本是一些上下文切换,可能还有一些内存副本(用于传输的数据)。)

特别是,TCP/IP 和 UDP/IP 接口(interface)(参见例如 UDP/IPv4 的 net/ipv4/udp.c)似乎没有任何用于内核端缓冲区的接口(interface)(除了直接访问位于内核内存中的 rx/tx 套接字缓冲区之外) )。

您可能听说过 TUX web server ,这是 Ingo Molnár 的子系统 patch to the Linux kernel。即使那不是“内核模块服务器”,而更像是用户空间进程可以用来实现主要在内核空间中运行的服务器的子系统。

提供 TCP/IP 和/或 UDP/IP 服务器的内核模块的想法就像试图用锤子拧螺丝一样。经过一段时间后,它会起作用,但结果不会很漂亮。

但是,对于回显服务器的特殊情况,它可能会在 IPv4(参见 net/ipv4/ )和/或 IPv6(参见 net/ipv6/ )之上,类似于 ICMP 数据包( net/ipv4/icmp.cnet/ipv6/icmp.c )。当且仅当你打算专注于内核端网络的东西时,我才会考虑这条路线,否则你学到的一切都是非常专业的,在实践中没有那么有用。

如果您需要为练习或其他东西实现内核端的某些东西,我建议您远离“应用程序”类型的想法(服务或类似的东西)。

相反,我强烈建议开发一个字符设备驱动程序,可能实现某种进程间通信层,最好是总线样式(即一个发送者,任意数量的接收者)。类似的东西有许多实际的实际用例(包括硬件驱动程序,以及像 kdbus 类型的东西这样的奇怪东西),所以你学到的任何东西都将适用于现实世界。

(事实上​​,一个回显字符设备——它简单地输出写入它的任何内容——是一个很好的第一个目标。虽然 LDD3 适用于 Linux 内核 2.6.10,但对于任何深入研究 Linux 内核开发的人来说,它应该是一本极好的读物。如果您使用更新的内核,请记住示例代码可能无法按原样编译,并且您可能需要对 Linux 内核 Git 存储库和/或内核源代码交叉引用器(如上面的 Elixir)进行一些研究。)

关于c - 在内核中使用 sock_create、accept、bind 等,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52804340/

相关文章:

c - 系统小程序 : Assertion failed - How can I solve?

c - C 中的命名空间

c - 用 C 模糊图像

linux - 是否真的需要重新编译内核才能进行 linux 驱动程序开发?

java - 向 DatagramSocket 添加超时-receive()

TCP 发送不返回导致进程崩溃

计算一个 32 位数字数组的奇数位置有多少个 1

regex - 基本的 Linux 正则表达式

linux - 更新特定行中文本文件中的特定字段

c++ - 无法连接到套接字