Linux串口上网的程序实现方法
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
- 3DES算法的FPGA高速实现(06-21)
- 基于DSP的Max-Log-MAP算法实现与优化(05-27)
- DSP中DMA操作的无阻塞请求实现(06-18)
- 二维DCT编码的DSP实现与优化(09-08)
- 基于DSP处理器上并行实现ATR算法(01-29)
- 基于DSP的H.324终端设计(05-27)