如何在自制操作系统写网卡驱动程序(1)
ninehua 2024-11-18 15:22 49 浏览
30天自制操作系统的解读文章已经更新到day23天了,基本的操作系统雏形已经完成了。不过我把这本书翻完后,发现这个操作系统的上限还是有点低。
怎么说这个操作系统的上限有点低呢?
这个操作系统包含了内存管理器,哨兵模式的超时器控制器,多任务控制器,多图层控制器,API接口库的设计等操作系统内核的重要模块,这份代码和linux系统的内核1.1版本相比的话,其实思路大体类似,毕竟使用的硬件是一样的。
但是这个操作系统离实际应用还有些距离。
为什么说它离实际应用还有些距离?
因为在这个操作系统之上开发的应用还是太少了,特别是缺少串口驱动,网卡驱动等与其他涉别通信的应用。
比如在day24,day25,day26,day27,day28,day29,day30等,也会开发一些较为实用的APP。
比如小蜜蜂游戏,图片查看器,文档浏览器,压缩软件等。
但没有了通信用的APP,它只能单机运行,对于一个简单的操作系统来说,如果只能单机运行,显然生命力就会很弱。
通信模块实现分析
所以,我就想如何给这个操作系统加上网络模块。
那么怎么给操作系统添加网络模块呢?
其实就是把网卡管理起来,也即是说cpu要控制网卡收发信息。
这跟cpu与键盘的交互,cpu与显示屏的交互其实有点类似,但是细节不同。
我们通过执行0x10号中断函数,来设置显示屏。
跟键盘交互时,先通过I/O来设置键盘控制器,然后当键盘有键按下时,就可以通过中断的方式通知CPU。
可以看到,CPU与外部设备打交道时,总是通过中断进行的。
特别是CPU控制键盘的过程,是比较常用的过程。
一般的外部设备都是让CPU先通过 I/O口来对自己的控制器进行设置,然后再通过中断把自己的信息传送给CPU的。
网卡也是外部设备,网卡也是先让CPU通过I/O来对自己的控制器进设置,然后再通过中断把自己的信息传送给CPU。
其实CPU就是一个计算器,它需要为很多外部设备提供计算,调度的功能才够完成功能丰富的操作系统。
外部设备的种类是非常丰富的,如果不同厂商的外部设备都需要一个自己特定的协议,才能跟CPU通信,那么对用户来说,一旦使用了这个外部设备,就不能更换其他厂商的产品了,这就非常不方便。
所以,有必要制定一个统一的标准Peripheral Component Interconnect,PCI,翻译:外部设备相互连接。通过硬件厂商可以让自己的硬件,比如网卡,声卡,显卡遵守这个PCI标准,从而降低自己的硬件设备被接受的成本。
这就造成了CPU与网卡之间,有个PCI控制器。CPU通过I/O口设置PCI控制器,PCI控制器再控制网卡即可。
所以,要在这个操作系统上控制网卡,实现网络通信,其实就是通过I/O口来设置PCI控制器,然后CPU就可以和网卡进行数据交换了,网卡收到数据会给CPU发送中断信号,只要我们编写合适的中断函数来处理网卡发送的数据,就像处理键盘发送过来的数据一样,这个操作系统就实现了联网的功能了。
不过,虽然道理上说的通,但是要具体实践起来,我们还需要一些参考。
那么linux的内核是开源的,可以去查看一下,顺便验证一下上述思路。
参考linux1.1内核
找到一份有详细注释的linux1.1内核代码:https://gitee.com/ydong08/linuxkernel1.1.git
上图linux1.1的主程序,可以看到这个主程序在一大堆初始化完成之后,就是一个永久运行的for循环了。
其实任务操作系统启动完之后,本身的程序都是一个永久的for循环。
我在这份代码中,并没有找到控制网卡的部分,可能linux1.1的内核并没有对网卡直接支持,我再找找。
不过这份代码的块设备相关的头文件中,找到了关于I/O的读写的语句:
可以看到,这里有用汇编写的port_read,port_wirte函数,这两个函数是用汇编写的,跟咱们在30天自制操作系统中解读的hari操作系统中的汇编是一样的。都是直接向I/O端口写控制字,然后从I/O端口拿数据。
这说明块设备作为外部设备与CPU交互的时候,也是先空过I/O端口来初始化的。
到这里,我们看到,在linux1.1中,硬盘作为外部设备,与CPU的通信,也是通过中断机制的。
那么继续找,就找到了硬盘的初始化函数:
这里,设置了硬盘的中断号,并且用I/O端口操作进行了一定的设置。这里的outb_p的实现也是汇编:
总的来说,通过查看linux1.1的内核代码,与咱们 30天自制操作系统中的系统内核代码相比,
在CPU 控制 外部设备的思路上,都是通过I/O端口 以及中断机制的。
所以,CPU控制遵守PCI协议的设备,应该也是通过I/O端口以及中断机制的。
既然1.1版本的内核里没有网络模块,可能这个版本太低了,我们直接看当前ubuntu20的5.13版本的内核。
这个内核是最新的版本,因为操作系统是现成的,所以这份代码就不用从网上下载了。
直接在ubuntu上运行如下命令:
可以看到内核版本是5.13.0-40的,所以内核代码所在的文件夹就是:
/usr/src/linux-hwe-5.13-headers-5.13.0-40
参考ubntu的linux5.13内核
打开这份内核代码,就看到一个名字为net 的文件夹,这说明这份内核代码里,是一定包含有网卡的基本驱动的。所以也必定有通过I/O端口来设置PCI控制器。
用pci作用搜索关键字,搜索到这设置pci的基本汇编语句:
这说明这份代码里,肯定对我们有用的。接着找,发现__raw_readb其实直接操作的指针,直接访问的内存了,并不是I/O操作。说明这个函数是在已经把网卡设备的地址通过I/O端口映射到内存地址之后,才运行的。 此时,访问内存地址,就相当于访问PCI所连接的网卡内的地址。
我们再看看最底层的用汇编写的对I/O端口的调用程序,我们直接搜索I/0操作的汇编指令,然后再找这些指令所在的函数有没有被PCI控制器的初始化函数调用。
这个汇编的写法,与之前的汇编写法有所不同,注意这些指令insbl,inswl,extbl,extwl,分别是往I/O上输入一个字节,输入一个词,输出一个字节,输出一个词,这是基本的I/O端口输入输出语句。
然后去搜索PCI控制器初始化函数,因为pci设备众多,所以,应该能搜索带很多pci设备
比如这张图上,我们大概搜索到了drivesr/net/wireless下的 pci_init.o模块,显然这是无线网卡的驱动程序,在链接的时候,使用了pci_init.o模块。
然后c4100.h文件中也有pci_init,可能ce4100也是某种pci设备。
然后最后一个pci_x86.h中的x86_default_pci_init函数,
不过这份代码似乎并不完全,也可能用了设计模式,所以很多逻辑不太好整理。
还是直接去官网下载一份源代码看:https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.6.18.tar.xz
这份源码跟5.13版本思路是一致的,可以认为是5.13版本的完整版,基本上在5.13版本里有的代码它都有,5.13版本没有的,它也有。
这份源码中可以搜索到很多个init_pci函数,说明是不同设备,不同场景对pci设备的初始化。
在pci_enable_device中,又调用了pci_enable_device_flags
而图中的pci_read_config_worl最终调用的是汇编I/O端口写操作,这似乎印证了“通过I/O端口配置PCI控制器”的思路。
包括do_pci_enable_device函数里,展开之后
发现里面的函数,凡是涉及到read,write的,最后都可以查到是汇编实现的。
那么当网卡收到数据时,会不会发送中断信号呢?我们也和容易搜索到了e1000网卡驱动的中断开启和关闭,如下图:
其中ew32函数是经过内联汇编实现的。
通过以上对linux内核1.1版本,5.13版本,5.6版本的源码查找,大体上基本印证了用I/O配置PCI控制器,然后用中断机制与网卡进行数据通信的思路是正确的。
所以,后面的步骤是:
- 整理出5.6版本e1000网卡的基本结构。
- 移植到30天自制操作系统教程上的操作系统harios上。
- 上一篇:无线网卡驱动-Ralink雷凌
- 下一篇:网络适配器驱动怎么安装
相关推荐
- 配合制导弹药!土耳其推出反无人机武器系统,可全天候拦截无人机
-
【军武次位面】作者:FriedrichLau据报道,日前土耳其军队装备了一款名为Sahin"沙欣"的反无人机武器系统。该系统由土耳其Aselsan公司开发,旨在摧毁迷你或小型无人机,...
- 威纶通常见问题18 威纶通触摸屏密码使用的相关介绍
-
密码1:屏右下角的系统设定列(向左的箭头)进入密码提醒:上传下载的默认密码均为6个1,若不慎忘记密码,因已加密所以原厂也无法解开,请妥善保管密码。若因不可抗力因素造成的忘记密码,只能将屏恢复出厂设置然...
- 轻松学会威纶通触摸屏上传与反编译
-
说到上传,大家并不陌生,上传顾名思义:就是把实际触摸屏画面上传到电脑EasyBuilderPro软件上,上传的作用是什么呢?可以修改触摸屏上原有的画面,所以说在上传这两字在工控中是非常重要的,接下来进...
- DLL 可以被反编译吗?(dll文件可以编辑吗)
-
DLL可以被反编译,但存在一定难度DLL(动态链接库)是一种二进制文件,包含了可执行代码和数据。虽然它不像高级语言源代码那样容易被理解,但可以通过一些反编译工具进行逆向分析。不过,反编译后的结果通常...
- 复古游戏反编译工具遭任天堂下架 工具名或为诱因
-
Reddit用户mhjhacker1近日发表文章称,自己开发的一款“复古主机游戏逆向工程”工具被其他用户使用,反编译了一款任天堂四十年前的游戏,因而遭到了Itch.io的下架。而相关的另外三个工具也遭...
- protobuf之序列化数据和反序列化数据基础知识
-
什么是protobufProtocalBuffers(简称protobuf)是谷歌的一项技术,用于结构化的数据序列化、反序列化。ProtocolBuffers是一种语言无关、平台无关、可扩展的...
- MT管理器-简单实战-去除启动页(mt管理器去除登录界面)
-
每次打开APP都要看着启动页2秒,很烦人,既然如此我们把它去掉吧。学过Android开发的都知道,APP的每个界面都是一个Activity,然后你点击桌面上的图标之后,其实是启动了这个...
- 这两个强大的开源C#反编译逆向工具,探索C#桌面应用的小秘密
-
C#的应用也比较多,有时候,我们想要研究一下别人的优秀的项目,可能会借助一些非常规手段来学习。下面,我就分享几款开源的C#反编译工具。dnSpydnSpy是一个用C#开发,开源的调试器和.NET汇...
- 一款开源的.NET程序集反编译、编辑和调试神器
-
致力于发掘、评测和推荐各种高效实用的工具和软件,帮助您在工作和生活中事半功倍。项目介绍dnSpyEx是dnSpy项目的非官方Fork维护版本,一款开源、功能强大的.NET反编译工具和调试器,可用于在没...
- 记一次噩梦般的经历--论学会反编译的重要性
-
最近在做一个android项目,因为非开源,github上也没购有私有库,所以就没有提交github管理。昨天我感觉写到了一定程度,一个小的版本已经出来了,于是就想U盘和网盘都备份一下。结果出现了下面...
- 奇!AI(人工智能)能不能反编译二进制代码为高级语言Java或者C?
-
一直很好奇某些软件的制作过程,使用的算法。因为自己实现的,写的稀烂,虽然功能达到了,但处理速度和处理效率很低下,于是也尝试使用一些反编译软件,如IDAPro软件。想看看人家怎么实现,怎么做到效果那么...
- 你知道 Java 中关键字 enum 是一个语法糖吗?反编译枚举类
-
持续创作,加速成长!这是我参与「掘金日新计划·10月更文挑战」的第7天,点击查看活动详情写下这篇文章,也纯属于是一个机缘巧合,我一个非常要好的朋友程,也是刚刚踏上工作岗位。这个问题也是他踏上岗位...
- SpringBoot项目Jar包加密,防止反编译
-
场景最近项目要求部署到其他公司的服务器上,但是又不想将源码泄露出去。要求对正式环境的启动包进行安全性处理,防止客户直接通过反编译工具将代码反编译出来。方案第一种方案使用代码混淆采用proguard-m...
- 安卓移动应用代码安全加固系统设计及实现
-
安卓平台已经逐渐成为最受欢迎的移动终端操作系统,基于安卓系统的软件应用数量众多,同时安全威胁也在不断增加。介绍了Android系统的安全风险及加固的核心技术,据此提出了一种安卓应用程序的安全加固系统,...
- 代码安全之代码混淆(代码混淆器是干什么的)
-
防止核心代码泄露以及代码合并每日辛辛苦苦码的代码被轻松破解?机密核心模块被盗用?数据库地址和语句暴露?……这些都是由代码未混淆加密,从而进行泄露的我们目前DLL文件存在的风险:一、直接引用二、反编译...