序言
出于网络模块中纷乱的epoll、wait_queue回调,过于简单实现的 iface_poll
设计,目不暇接的句柄处理,以及这导致的一些资源冲突,以及这些资源冲突导致的进一步的设计的妥协(一系列的全局资源),我实验性地尝试重构整个 net
模块,尝试简化并缕清 iface
- socket
- inode
的关系,压缩整个模块所需要的抽象层次,目的是减少重复实现,实现接口与资源的解耦,优化整个 net
子系统的api,并在这基础上进一步实现先前由于种种未能实现的功能、解决潜在的bug:
初步设计
以下设计均为我于 2024-08-03T16:00:00Z 作出的大致设计,非常非常非常欢迎 各位使用过 or 曾经开发过网络子系统的各位开发者给出建议。
SocketInode
作为kernel中对资源的一般性抽象,负责映射底层Socket的接口,并管理相关的 epoll
wait_queue
资源。
Socket
trait,规范通用socket行为
INET Socket
需要 Iface 的资源
UNIX Socket
kernel communication 的 socket 抽象
Iface
持有 Inet Socket
的硬件资源,几乎所有 Inet Socket
的行为都要 poll_iface
。这也是需要分开管理 Inet Socket
的原因。
累了明天再补充,反正这么晚也没人看,如果要追更直接回帖我会看到的
1 个赞
Inet Socket 设计
整个socket是一个巨大的state machine,需要根据state所在层次详细拆分。
Bound & Unbound State
Bound & unbound 直接作为 Inet Socket 的第一层状态机,以表明其是否绑定 Iface
:
Socket Family Specific State Machine
net设备的驱动也应该重写,现在的e1000驱动是直接复制虚拟网卡的驱动改的,重复了
1 个赞
你的意思是e1000e和vitrtonet的驱动很相似,可以把驱动抽象出来给不同的网卡复用吗?
有一些可以抽象出来的东西,但并不是必须的
主要是我觉得这部分驱动的代码比较啰嗦,就比如每个驱动里的struct和函数的名字都带前缀,这完全没必要(写成smoltcp里的几种Socket的形式会比较好
你别说smoltcp的几种Socket看起来简洁,但是我外面想要复用他的enum分类麻烦得要死,rust 又不支持 cpp 的 SFINAE
,导致我每个特化都要单独写个tcp / udp函数,要不就得在外面加一层 enum 或者 trait ,有点好气又好笑
SFINAE is the best thing in the world. ——鲁迅
新issue: [BUG REPORT] socket shutdown wrong implemented · Issue #887 · DragonOS-Community/DragonOS · GitHub
目前该实现是完全错误的,这可以参考 linux glibc 对于 shutdown() 中 how 的值定义:
https://www.man7.org/linux/man-pages/man2/shutdown.2.html#NOTES
The constants SHUT_RD, SHUT_WR, SHUT_RDWR have the value 0, 1, 2, respectively, and are defined in <sys/socket.h> since glibc-2.1.91.
这是重构时发现的问题,暂时未有已知造成的影响,也会在重构过程中得到修复。
注:其实 posix 标准并没有规定 SHUT_RD, SHUT_WR 和 SHUT_RDWR 的具体值,这里特指 linux glibc 的实现
关于Socket重构后一些与epoll管理相关的问题,对于维护socket的epoll_items的list,主要是为了在epoll的回调中获取到管理socket文件的epoll_guard来判断socket是否加入到其ready_list中,那么现在每种socket结构体下都有一个epoll_items,对于这个list的操作目前有add_epoll,remove_epoll,clear_epoll以及epoll的回调,这些操作是不是应该放在Socket的外层统一管理,比如inode?或着Socket trait中公共实现
目前非inet的socket的缓冲区由socket各自实现,考虑将其读写逻辑基本一致,是不是单独成结构体开放申请、读写、销毁接口给各个非inet socket(inet socket缓冲区由smoltcp维护了)服务会更简洁,可维护性扩展性会更好?
可以考虑,只是内核-用户态层面的数据所需要的缓冲区应该是同构的,linux上的实现是重用的吗?