小孩没娘,说来话长,一切都要从LwIP说起。大约是06年9月,本人在二姨的坛口发布了一篇小文——《uC/OS-II 平台下的 LwIP 移植笔记》。自此一发不可收拾,开启了一段我与LwIP从相识到相知的艰难历程。一年多的时间,对LwIP的使用获得的点点滴滴的知识聚沙成塔、集腋成裘,终于在08年汇成了一本大部头的书《嵌入式网络系统设计——基于 Atmel ARM7 系列》。这本书详细讲解了如何从零开始构建一个带实时操作系统的嵌入式网路通讯系统应用的完整技术实现过程,涉及单片机软、硬件开发、uC/OS-II实时内核 、LwIP协议栈移植及应用等相关知识。这本书的反响相当不错,好多人给我发 msn(可惜这么好的一个即时通讯工具就这么被微软放弃了,好多联系人就此失联,?)或邮件咨询相关问题。彼时的uC/OS-II和LwIP是单片机开发者眼中的两大神器,属于基础的不能再基础的核心软件,是我长时间仰望的大神级别的存在。作为一名有梦想的程序猿,有朝一日能够像这些大神一样 ,参与甚至主导这样的核心基础软件的研发,幸之甚哉。梦想的种子一旦种下,就会在心底的某个地方悄悄地生根、发芽直至成长为一颗参天大树。清人山阴金先生言:”志之所趋,无远弗届。穷山距海,不能限也。”要想到达志之所趋之地,非一时一日之功可至。所以,写笔记以至写书都是为了让自己静下来,把脑海中那些有关uC/OS-II、LwIP的琐碎知识、技巧重新整理、归纳形成系统的知识,在思想层面与大神在线交谈,将大神的设计思想消化吸收,变成滋润自己的丰富营养。

在我原来的写作计划中,这本书的出版只是一个开始,接下来还要写第二本——系统介绍 LwIP 包含的 ppp 协议栈的移植、应用及设计实现等相关内容。如此一步一步、踏踏实实地走下去,梦想终将得偿。但,事与愿违,自08年书出版后,我的工作重心从单片机转到了嵌入式Linux系统,用到LwIP的机会从此归零。研发的产品也愈发复杂,可自由支配时间愈发变少。当然,最重要的一点是——ppp协议族在我的眼里还是太复杂了,涉及lcp、chap/pap、ipcp等多个协议之间的交互与协作。完成ppp移植并且应用只是第一步,要想变成铅字,我必须了解全部的技术细节,完全清楚ppp的相关工作原理并消化吸收后才能变成指尖下流动的文字明明白白地展示给读者。这也是我实现梦想必须要完成的工作。但可惜的是,那时的我对ppp没有任何知识储备,并且也无法拿出足够的时间从一加一等于二开始研究。没有完整时间、没有知识储备——能力、精力二者均不可得,信心自然就不足了,自然就没有把握把这件事情做好了,自然就不敢“硬”挤出时间继续我的写作计划了。于是,梦想的脚步在那时被按下了暂停键,LwIP、协议栈、核心基础软件这些标志性的东西被我悄悄地封存在了内心最隐秘的角落。

如今时间已经来到了二零年代,一个疫情肆虐、暂未看到结束迹象的年代。我的自由可支配时间多了起来。十余年的时光,各种复杂项目的锤炼也让我的知识储备和技术能力突飞猛进,远非当年的我可比。21年春节前与友人聊天,聊起开源软件,特别是嵌入式网络协议栈。他说适用于资源受限的单片机系统的网络协议栈可选择面很窄,主要就两款:LwIP和ThreadX NetX,前者可适配RT-Thread、uC/OS-II之类的多种rtos,而后者只能适配ThreadX,咱们中国人自己的开源网络协议栈还没有。说者无心,听者有意,那一刻我知道梦想之树到了开花结果的时候了。只不过时移势易,计划需要做些调整。没必要继续十余年前未竟的写作计划了,因为我的实力足以支撑我直接动手开发自己的网络协议栈了,无须从LwIP那里汲取营养了。于是,梦想的脚步在暂停十余年后再次向前迈出。

动手之前,需要先取个名字,想来想去还是直白一些更好。既然我要研发的是开源网络协议栈,直译成英文就是“open net protocol stack”,那就直接取英文全称的每个单词的首字母,就叫做onps栈,简单明了,还容易记。终于,历时6个月余,我顺利地完成了onps栈的1.0版。1.0版提供完整地ethernet/ppp/tcp/ip 协议族实现,同时提供 sntp、dns、ping 等网络工具,支持以太网环境下 dhcp 动态 ip 地址申请,也支持动态及静态路由表。不同于LwIP,协议栈还封装实现了一个伯克利套接字(Berkeley sockets)层供用户继续按照以往的编程经验与习惯使用onps栈开发自己的通讯应用。同时,为了方便用户使用、简化用户编码,协议栈还简化了传统BSD socket 编程需要的一些繁琐操作,将一些不必要的操作细节改为底层实现,比如 select/poll 模型、阻塞及非阻塞读写操作等。

为了适应单片机系统对内存使用极度变态的苛刻要求,onps 协议栈在设计之初即考虑采用写时零复制(zero copy)技术。用户层数据在向下层协议传递过程中,协议栈采用 buf list 链表技术将它们链接到一起,直至将其发送出去,均无须任何内存复制操作。另外,协议栈采用 buddy 算法提供安全、可靠的动态内存管理功能,以期最大限度地提高协议栈运行过程中的内存利用率并尽可能地减少内存碎片。

不同于本世纪 00 到 10 年代初,单片机的应用场景中 ucosii 等 rtos 尚未大规模普及,前后台系统还大行其道的时代,现如今大部分的应用场景下开发人员选择使用 rtos 已成为主流。因此,协议栈在设计之初即不支持前后台模式,其架构设计建立在时下流行的 rtos(RT-Thread、ucosii/iii 等)之上。协议栈移植的主要工作也就自然是针对不同 rtos 编写相关 os 适配层功能函数了。当然,如果你有着极其特定的应用场景,需要将 onps 栈移植到采用前后台模式的单片机上,我的建议是保留 tcp/udp 之下协议层的通讯处理逻辑,调整上层的系统架构使其适应目标系统运行模式。

其实,协议栈完成开发只是实现梦想的第一步。用户在使用过程中遇到的各种问题,协议栈的改进建议,新版本的发布都需要一个平台。于是我又在阿里云购买了一台云服务器,带宽1Mbps?(资金有限,实在没办法),在上面部署了一个WEB服务器,作为onps栈的技术交流及官方资讯发布平台。另外我还为onps栈注册了一个域名:onps.org.cn,作为onps栈的官网访问地址。onps栈的源码可以从码云gihub上获取。

历尽千辛万苦,onps栈如今已开源。新莺初啼,总免不了会有诸多不尽如人意的地方。期望各位多多使用,把使用过程中遇到的问题通过onps栈的技术交流社区提交给我,让onps栈能够快速迭代,早日比肩LwIP?,为国产核心基础软件的进步贡献你我一份微薄的力量!