SNULL网络设备驱动

SNULL指Simple Network Utility for Loading Localities,是区域装载的简单网络工具,可以用来实现串口上网。

SNULL的优点在于不和任何硬件相关,而只是操作从内核分配的一些内存。所以在任何操作系统上都能实现而不用在驱动里进行硬件配置 ,具有很好的移植性。易于理解,可以对照网卡DM9000驱动程序和LDD十七章学习。


net_device结构体

net_devic结构体描述了网络设备数据和操作。部分定义如下:

struct net_device {
 char            name[IFNAMSIZ];    //网络设备的具体名字
 struct net_device_stats* (*get_stats)(struct net_device *dev);
 struct net_device_stats stats; 
 //网卡发送包的个数等等,ifconfig eth0看到的东西
 ...
 void   *priv; 
 int   (*hard_start_xmit) (struct sk_buff *skb,
          struct net_device *dev);
 ...
 int   (*open)(struct net_device *dev);
 int   (*stop)(struct net_device *dev);
 ...
 }

其中的open、stop就对结构体成员进行操作。priv是一个私有的数据指针,具有举足轻重的作用。它的获取是使用函数

net_device *dev;
dev->priv = netdev_priv(dev)

获取。或者类似DM9000写为:

static struct ednet_priv *GetPrivate(struct net_device *dev)
{
return netdev_priv(dev);
}

其中ednet_priv是自己定义的来封装所需私有数据的结构体:

struct ednet_priv {
   struct net_device_stats stats;
   struct sk_buff *skb;
   spinlock_t lock;
};

相当于强制类型转换返回ednet_priv类型的指针(因为priv指针是void*类型,等着用户重定义),它指向net_device的私有数据priv区。

不能直使用dev.priv。具体原因,LDD上说法是:

priv成员的作用和字符驱动程序中的private_data指针作用类似。priv指针是于net_device结构一起分配的,出于性能和灵活性方面的考虑,不鼓励直接访问priv成员。

查看netdev_priv源代码:

static inline void *netdev_priv(const struct net_device *dev)  
{  
return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN);  
}  

priv虽然是net_device的成员,但内存分配的时候其实是紧挨着net_device结构体的,因而上面这个函数返回net_device的末地址并且要满足字节对齐,也就是priv的首地址。


SNULL

SNULL参见LDD书及其源代码[7]。NULL驱动编译后ftp传送到MINI2440上,加载后ifconfig结果如下:

图片

sn0和sn1是两个虚拟网络设备,它们获得了局域网IP地址和其他配置信息。


NetRouter

把SNULL(相当于一个没有硬件实现的虚拟网卡)中再加入两个字符设备(相当于buffer),用来存储网卡的收发数据,实现串口上网的功能。至于为什么要加入字符设备来作buffer而不是直接在SNULL中读写串口数据,这是因为在驱动层无法类似调用read(fd,buffer,len),只能想一个中转数据的方法。把数据在应用层再用一个应用程序fd=open("/dev/ttySAC1",O_REWR | O_NOCTTY读写到串口驱动里。

加载驱动ed0如下:

图片


当上层应用需要传输数据包时,内核会自动执行下面的流程调用来从串口发出数据。画图采用可以在线协作的ProcessOn。

图片

.ndo_start_xmit定义在net_device_ops操作函数集合结构体中,绑定到内核。

ed[ED_TX_DEVICE]是定义的作为接受缓冲区的字符设备,kernel_write相当于它的一个方法。

memcpy把驱动读到的来自上层的数据拷贝到字符设备私有buffer中。

TBD


Reference

[1].http://my.oschina.net/lvyi/blog/325785

[2].http://blog.sina.com.cn/s/blog_478ef86301007vq7.html

[3].LDD.Page491~509

[4].http://blog.csdn.net/npy_lp/article/details/7090541

[5].http://blog.csdn.net/fareast8612/article/details/7480246

[6].http://www.ibm.com/developerworks/cn/linux/l-serialnet/

[7].https://github.com/yql612679/linux-drive



Previous     Next
/
Published under (CC) BY-NC-SA in categories arm  tagged with