linux下网络设备驱动简要过程

最近项目中,应用层要对CAN帧接收的时间戳进行记录,由于BSP中的CAN驱动是做成网络接口驱动通过socket让应用层实现收发的,所以较系统地研究了一遍linux下的网络子系统的框架,这里总结记录一下:
1.对socket的应用编程,以前主要只是简单地应用write和read进行收发,这些接口只是简单地对需要收发的数据内容进行操作,应用起来也很方便,所以就想着在数据内容里面增加时间戳数据,其实后来通过驱动的阅读,应用recvmsg接口可对一些比较复杂的附加信息进行读取,就比如时间戳信息; 但这个接口用起来还是比较复杂的,首先需要使用setsockopt对关心的附加信息进行配置,然后需要应用CMSG_DATA等宏对读取出来的msg进行分析;但是,不管如何,设备驱动的数据接收中断中都需要对接收的时间点进行记录,注意一般单独写的网卡驱动可能没做这个工作; 
2.源码路径:网络设备驱动源码一般放在./drivers/net/目录下(本文称它为接口驱动),而网络协议驱动(本文称它为协议驱动)以及网络框架源码则一般放在./net/目录下;新网卡驱动的实现应该主要集中在接口驱动和协议驱动的相关工作;
3.进一步地,在第2点描述的基础上,比如,所有的CAN接口的接口驱动都放在./drivers/net/can/目录下,包括CPU自带的CAN接口以及外接的sja1000等CAN接口;这里的驱动负责使用register_netdev()接口注册网络设备,并直接对硬件进行操作,如CAN接口的寄存器配置,数据的发送以及对接收FIFO的读取等,一般的读取会使用到中断,在中断处理函数中将FIFO中数据读到以sk_buff结构封装的内存数据对象skb中,并将这个skb通过netif_rx()发送到数据接收队列中,skb中的协议域protocol成员必须填充,比如设置成AF_INET、PF_CAN等;
4.更进一步地,第3点中描述的netif_rx中,判断是否需要加时间戳(默认不需要,如需改变,应用层可通过setsockopt接口设置SO_TIMESTAMP属性),然后启动软件中断NET_RX_SOFTIRQ,相对应的中断处理函数net_rx_action()将被启动进行接收这些数据并按相应的协议域进行处理(这个处理由后面将要讲到的协议驱动进行);
5.进一步地,在第2点描述的基础上,所有的协议驱动都放在./net/目录下,如tcp、udp以及这里的CAN_RAW协议驱动文件./net/can/raw.c;包括ISO15765的网络层协议也就是在协议栈中的这个位置;
6.更进一步地,第5步所述的协议驱动,主要负责使用proto_register()接口进行协议类型的注册,以及向上层提供的操作接口,包括数据收发处理,这里的接口最终会调用接口驱动中提供的接口;
7.为应用层提供的socket相关接口都在./net/socket.c当中,如recvmsg()、setsockopt()等接口。

猜你喜欢

转载自q2768717191.iteye.com/blog/2229010