要处理从用户空间到您的协议的通信,请将您的协议注册到内核sockets API。这允许您从用户空间创建一个普通的套接字。
查看相关code samples 的蓝牙/RFCOM 套接字实现。
static const struct proto_ops rfcomm_sock_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.bind = rfcomm_sock_bind,
.connect = rfcomm_sock_connect,
.listen = rfcomm_sock_listen,
.
.
.
.accept = rfcomm_sock_accept,
};
static const struct net_proto_family rfcomm_sock_family_ops = {
.family = PF_BLUETOOTH,
.owner = THIS_MODULE,
.create = rfcomm_sock_create
};
要注册协议,您必须填写proto_ops 结构。这个结构遵循在内核其他地方观察到的object oriented pattern。该结构定义了一个接口,供开发人员实现自己的套接字接口时遵循。
实现接口定义的bind、connect、listen等函数,并将函数指针赋值给结构入口。为操作接口未涵盖的功能定义 ioctl。
您最终得到一个结构,稍后您将其嵌入到我们从 create 函数返回的 socket struct。
Struct net_proto_family 定义了一个新的协议族。这个结构包括 create 函数,你的函数实现应该填充一个由 proto_ops 结构填充的套接字结构。
然后用sock_register注册家庭,如果一切正常,你应该能够从用户空间创建一个合适的套接字。
在内部,协议可能应该使用 skbuffs(请参阅 here 和 here)与网络设备进行通信。
skbuffs 是 linux 内核中处理网络数据包的通用方式。数据包被网卡接收,放入一些skbuff,然后传递给网络栈,网络栈一直使用skbuff。
这是在linux内核中实现网络协议的基本数据结构和io路径。
我不知道有一份文件从头到尾描述了这个过程。
来源与您同在。