如何编写网卡的驱动程序

去年夏天,我在一个周末的下午,坐在家里的电脑前,尝试编写我的第一个Linux网络驱动程序。
那时候,我刚刚接触Linux内核编程,对设备驱动程序的概念还比较模糊。
我打开电脑,屏幕上跳出了Linux内核源代码的目录,里面密密麻麻的文件让我有些眼花缭乱。

我打开了一个叫做"drivers"的文件夹,里面又分了许多子文件夹,比如"net"、"char"、"block"等。
我找到了"net"文件夹,里面都是和网络设备相关的驱动程序代码。
我选中了一个看起来比较简单的驱动程序,开始阅读它的源代码。

阅读过程中,我注意到了几个关键的概念:字符设备、块设备、网络设备。
我意识到,网络设备在Linux系统中有着特殊的处理方式,它基于BSD Unix的socket机制,使用特定的数据结构进行数据传递。

我继续阅读,发现编写网络驱动程序需要关注几个基本方法,比如初始化、打开、关闭、发送、接收等。
这些方法看起来很简单,但实际上涉及到很多细节,比如硬件帧头的处理、地址解析等。

我花了几个小时的时间,试图理解这些概念,但仍然感到有些困惑。
我决定先从最简单的发送和接收功能开始,一步一步地深入。

突然,我想到了一个问题:如果网络设备在发送数据时,硬件忙了怎么办?我意识到,这涉及到流量控制的问题。
我决定去查阅一下相关的资料,看看如何处理这种情况。

就这样,我开始了我的Linux网络驱动程序编写之旅。
虽然现在还有很多问题没有解决,但我相信,只要不断学习和实践,我终将能够掌握这个技能。
等等,还有个事,我突然想到,编写驱动程序的过程中,调试也是一个非常重要的环节。

怎样编写Linux设备驱动程序?

Linux驱动程序跟Unix一样,但比Windows的复杂。
Linux下写驱动,简单方便,但功能受限,得自己动手。
我这周刚搞定一块多媒体卡的驱动,有点心得。

系统调用是内核和应用的接口,驱动程序是内核和硬件的接口。
它让应用像操作文件一样操作硬件。

举个例子,写个简单的字符设备驱动,了解其工作原理。
虽然它啥也不干,但能让你明白Linux驱动是怎么玩的。

如何编写Linux操作系统的设备驱动程序

哈,你这段写的是不是就是我上次跟你提的Linux驱动开发笔记啊?看着挺全面的,把驱动程序在Linux里的角色、功能和设备文件的关系都捋明白了。

说到Linux驱动开发,确实挺有意思的。
你对比Unix和Windows驱动,抓得挺准。
Linux这边就是思想简洁,用现成内核函数多,但像你说的,有时候得自己造轮子,比如那个缓冲区管理啊,块设备缓存啊,确实得自己琢磨。
调试是挺头疼,我之前在虚拟机里搞那个网络卡驱动,卡死的时候只能硬重启,每次都跟玩俄罗斯方块似的,得一步步回退。

你提到参考了Writelinuxdevicedriver、清华BBS那些资料,还自己修正了错误,这很关键啊。
我上次自己捣鼓那个GPIO驱动,就吃了资料过时的亏,光看理论没跑实验,结果寄了。
后来对照内核源码才改过来。

设备号这块我也踩坑过。
之前写个USB设备驱动,主设备号申请错了,结果系统识别不了,搞得用户那边以为我的驱动是个摆设。
后来去改init模块代码,那叫一个头大。
所以你说的"设备文件的主设备号必须与驱动程序申请的一致"这句话,绝对是真理,敲黑板的那种。

核心态切换这事儿也真实。
上次写中断处理程序,忘了加锁,结果导致死锁,CPU利用率飙到1 00%,只能硬重启。
那种感觉,就像开车突然被卡死在马路上,只能下车推车一样,挺崩溃的。

你最后那个"如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了"说得特别实在。
这就是内核编程的代价吧,压力真不小。
不过话说回来,把驱动写好了,那种掌控硬件的感觉,还是挺爽的。

反正你这篇笔记写得挺扎实,把基础概念都讲清楚了。
后续你想分享具体代码实现或者调试技巧,随时跟我说,我这边也有点东西可以交流。

浅谈一下LINUX驱动开发中的红外(IRDA)程序

哈,红外遥控这东西,我琢磨过一阵子。

就说2 02 3 年我在上海搞那个智能家居展的时候吧,看到一堆堆的遥控器,什么品牌都有,但原理都差不多。
它好在哪儿呢?主要就是省电,成本低,信号也不容易乱串。
不像Wi-Fi或者蓝牙,你家路由器一开,邻居的设备也能冒出来。
红外线它就特实在,发出去就沿着直线走,遇到墙就没了。
所以同一牌子电视、空调,用一样的遥控器捣鼓,不会有啥冲突。

我之前玩开发板的时候,专门研究过NEC协议。
这个协议是真常用,很多国产电视、空调都用它。
特点就是时序挺固定的,比如它那个5 6 0us的载波脉冲,挺明显的。
你发个逻辑1 ,得先有个5 6 0us的脉冲,然后跟着一个1 .6 8 ms的低电平;发个逻辑0,就是5 6 0us脉冲,然后跟着一个5 6 0us低电平。
接收头那边,有脉冲就是低电平,没脉冲就是高电平,这个好认。

数据格式也挺有意思,同步码开头,然后地址码、地址反码、控制码、控制反码,一整串。
为啥要加反码?我理解是为了提高抗干扰能力,收完数据再跟反码比一下,不一样就重发呗。
这设计是真周到。

学的时候,我专门画了时序图,对着示波器抓波形,那会儿可真是抓得头发掉。
解码过程,就是等那个下降沿,一进来就判断脉冲宽度,是1 ms还是5 00us,然后一帧数据收完了,再跟地址反码和控制反码比,对上了才认为成功。
这个过程,中断函数用得特别多,你得精确捕捉到那个脉冲的变化。

写驱动的时候,真是个坑。
你得先定义个结构体,把时序参数都标清楚,比如5 6 0us脉冲宽度、1 ms高电平、5 00us高电平这些。
然后编写中断服务程序,捕捉到下降沿就启动定时器,去测高电平持续多久,是1 ms还是5 00us,一帧数据收完后,再比对反码。
最后把这些数据解析出来,变成你能控制的具体命令,比如开关灯、调节音量啥的。

编译调试那会儿,我还用Makefile搞过,每次改了代码,编译、烧录、测试,一套流程走下来,有时候能折腾半天。
就是得确保稳定性,遥控器一挥,指令得准确无误地到设备那儿去。

反正,红外遥控驱动这东西,真要搞明白,得下一番功夫。
时序、解码、抗干扰处理,每一步都不能含糊。
学扎实了,以后做嵌入式开发,控制各种设备就容易多了。
不过说实话,现在很多新设备都用蓝牙或者Wi-Fi了,红外遥控感觉是有点被边缘化,但老设备一大堆,还得搞懂不是?