微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Linux串口上网的程序实现方法

Linux串口上网的程序实现方法

时间:05-10 来源:互联网 点击:

printk(ednet:error%iregisteringpseudonetworkdevice%sn,

err, ednet_dev.name);

return err;

}

ednet_dev的name域是接口名,ednet_module_init()中赋予网络接口的名字为ed0,如果本网络设备被加载,使用ifconfig命令可以看到ed0。

[root@localhost pku]# /sbin/ifconfig

ed0 Link encap:Ethernet HWaddr 00:45:44:30:30:30

inet addr:192.168.3.9 Bcast:192.168.3.255 Mask:255.255.255.0

UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1

RX packets:0 errors:0 dropped:0 overruns:0 frame:0

TX packets:0 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:100

RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

我们看到我们的伪网络接口没有Interrupt和Base address,这是因为这个伪网络接口不和硬件打交道,也没有分配中断号和IO基址。否则,如果你看一个实实在在的网络接口(如下面的eth1),可以看到它的Interrupt号是11和IO Base address是0xa000。

eth1 Link encap:Ethernet HWaddr 50:78:4C:43:1D:01

inet addr:192.168.21.202 Bcast:192.168.21.255 Mask:255.255.255.0

UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

RX packets:356523 errors:0 dropped:0 overruns:0 frame:0

TX packets:266 errors:0 dropped:0 overruns:0 carrier:0

collisions:0 txqueuelen:100

RX bytes:21542043 (20.5 Mb) TX bytes:19510 (19.0 Kb)

Interrupt:11 Base address:0xa000

ednet_dev的init域是一个函数指针,指向用户定义的ednet_init()例程。ednet_init()添充net_device结构,只有ednet_init()初始化成功后,系统才被加入到设备链表中。ednet_dev的初始化例程ednet_init()如下:

#ifdef LINUX_24

int ednet_init(struct net_device *dev)

#else

int ednet_init(struct device *dev)

#endif

{

ether_setup(dev);

dev->open = ednet_open;

dev->stop = ednet_release;

dev->hard_start_xmit = ednet_tx;

dev->get_stats = ednet_stats;

dev->change_mtu = ednet_change_mtu;

#ifdef LINUX_24

dev->hard_header = ednet_header;

#endif

dev->rebuild_header = ednet_rebuild_header;

#ifdef LINUX_24

dev->tx_timeout = ednet_tx_timeout;

dev->watchdog_timeo = timeout;

#endif

/* We do not need the ARP protocol. */

dev->flags |= IFF_NOARP;

#ifndef LINUX_20

dev->hard_header_cache = NULL;

#endif

#ifdef LINUX_24

SET_MODULE_OWNER(dev);

#endif

dev->priv = kmalloc(sizeof(struct ednet_priv), GFP_KERNEL);

if (dev->priv == NULL)

return -ENOMEM;

memset(dev->priv, 0, sizeof(struct ednet_priv));

spin_lock_init( ((struct ednet_priv *) dev->priv)->lock);

return 0;

}ether_setup()填充一些以太网的缺省设置。dev->hard_header_cache=NULL表示不缓存向本网络接口回复的ARP网络数据包。IFF_NOARP的标志设置表明本网络接口不使用ARP。ARP的主要功能是获得通信对方的网络接口的硬件地址,本文的伪网络接口的物理地址是程序中设定的伪物理地址,所以我们不需要ARP协议。SET_MODULE_OWNER(dev)这个宏是设置dev结构中owner域(定义为struct module *owner;),使得它指向本模块本身。与字符设备一样,本网络设备也需要定义在其上的操作例程。下面就对ednet_init()中用户定义的设备操作函数做进一步说明。整个伪网络设备操作调用结构如图6所示。

图 6

由图6我们看到,ednet_rx()并不是网络设备的一个操作,而是模块中的一个函数。在实际的网卡驱动程序中,当网卡确实接收到数据的时候,由网络中断唤醒等待接收数据的用户进程,也就是说,ednet_rx()应该由那个网络中断处理例程调用。我们这里并没有中断,所以字符设备的device_write()可以看成是一个中断例程,也就是说,用户空间往字符写操作的时候,也就调用了网络设备的数据接收内核例程ednet_rx()了。然后ednet_rx()会把原始的数据包发送到TCP/IP上层进行处理,这一切均依赖于内核API 函数netif_rx()。ednet_rx()就需要sk_buff数据结构(linux/skbuff.h>中定义),用来存放从网络接口接收到的原始网络数据,分配后的sk_buff结构将在TCP/IP协议栈上被释放掉。

下面介绍一下网络设备的主要操作例程ednet_open()、ednet_release()、ednet_tx()、ednet_stats ()、ednet_change_mtu()、ednet_header()。网络设备文件操作结构struct net_device(linu

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top