在尝试了解有关Linux内核网络的更多信息时...我有一个内核模块,其中包含一个在TCP之上运行的协议。它几乎是我正在试验的应用层协议。调用通过从用户空间执行的普通系统调用接口传入。
因此,我的(TCP上层)模块内的网络调用通常看起来像这样......
ret = sock->ops->connect(sock, (struct sockaddr *) &myprot.daddr,
sizeof(myprot.daddr), flags);
我在KM中成功使用了sendmsg / recvmsg来发送和接收客户端到服务器的数据(来自两个独立的内核实例)。 KM中的呼叫通常如下所示:
ret = sock->ops->sendmsg(iocb, myprot.skt, &msg, sizeof(struct msghdr));
ret = sock->ops->recvmsg(iocb, sock, msg, total_len, flags);
我现在想要了解的是如何以及何时使用sk_buff来做同样的事情。即何时使用系统调用,例如我上面使用的,以及何时通过sk_buff直接访问网络堆栈来发送和接收数据。
我发现了许多如何使用sk_buff从传输层中发送和接收数据的示例,但是没有来自传输上方的层,也包含在内核模块中并使用sk_buff。
更新澄清。
我已经覆盖了struct proto_ops并替换了我自己的协议使用的成员方法,这些方法对应于来自用户空间的系统调用。我知道sk_buff是内核的缓冲系统,也是数据包入队的地方。然而。我没有看到任何理由不能使用struct proto_ops的协议特定函数,它还处理套接字和排队的数据(尽管在更高级别)。所以在我看来有两种方法可以访问sk_buffs,具体取决于你想要访问它们的位置。
如果我在传输层工作并想要访问网络堆栈中的任何数据(例如transport,ip,mac),我可以直接访问sk_buffs,但如果我在传输层之上工作,我会使用与系统调用相对应的抽象协议特定成员函数。毕竟,他们最终都在使用sk_buffs。
我想我的困惑,或者我想通过了解这两种访问sk_buffs的方式的区别以及从哪里来确认我是做对还是错......如果我发送数据在内核中从TCP传输,而不是我可以使用与TCP相关的proto_ops系统调用,除非我需要更多的控制,然后我将使用较低级别的skb函数来管理队列。
答案 0 :(得分:0)
不确定理解因为你想为了同一目的而使用不同的东西。 proto_ops
中的sock->ops
是在通信系统调用期间调用的操作。 sk_buff
是内核的套接字缓冲系统;它是数据包入队的地方。
proto_ops
sk_buff
与{{1}}同样的事情是不可能的,如果这些结构中的一个可能是无用的。