Linux中国  设为主页
 收藏本站
 
当前位置: > 首页 ->Linux技术 ->嵌入式系统 ->Linux串口上网的简单实现
·怎么样从FireWire 设备引导Linux ·教你怎么样从FireWire 设备引导Linux ·嵌入式程序员应知道的几个基本问题(2) ·嵌入式程序员应知道的几个基本问题(1) ·Linux 助力 Nokia 770 ·嵌入式Linux 中的应用中的GTK+ ·嵌入式系统 Boot Loader 技术内幕 ·FREEBSD下使用crunch集成编译程序 ·ucLinux下sqlite数据库移植全攻略
  相关分类: 
入门与提高
系统管理
网络应用
嵌入式系统
内核研究
服务器相关
发行版专区
Linux程序设计
Linux安全
BSD相关
桌面应用
  站内搜索: 
热门文章排行
热门文章排行 嵌入式系统 Boot Loader 技术内幕 (04-22)
BusyBox 简化嵌入式 Linux 系统 (04-22)
Linux下的硬件驱动——USB设备(下)(04-22)
Linux串口上网的简单实现 (04-22)
Linux下PCI设备驱动程序开发 (04-22)
精采文章排行
精采文章排行 BusyBox 简化嵌入式 Linux 系统 (04-22)
Linux 助力 Nokia 770 (04-22)
嵌入式Linux 中的应用中的GTK+ (04-22)
嵌入式系统 Boot Loader 技术内幕 (04-22)
FREEBSD下使用crunch集成编译程序 (04-22)
 

Linux串口上网的简单实现

作者:李素科    来源:IBM DW中国   点击:   日期:2007-04-22 [收藏] [投稿]

  IE是否经常中毒?推荐您


我们看到我们的伪网络接口没有 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(<linux/netdevice.h>中有定义)中定义了指向以上函数的函数指针的原形:


ednet_open:   int  (*open)(struct net_device *dev);
	ednet_release:  int  (*stop)(struct net_device *dev);
	ednet_tx:     int  (*hard_start_xmit) (struct sk_buff *skb,struct net_device *dev);
ednet_stats:   struct net_device_stats* (*get_stats)(struct net_device *dev);
ednet_change_mtu:int	(*change_mtu)(struct net_device *dev, int new_mtu);
	ednet_header:  int  (*hard_header) (struct sk_buff *skb,
						struct net_device *dev,
						unsigned short type,
						void *daddr,
						void *saddr,
						unsigned len);
	

操作int ednet_open(struct net_device *dev)的作用是打开伪网络接口设备,获得其需要的I/O端口、IRQ等,但是本网络接口不需要和实际硬件打交道,所以不需要自动获得或者赋予I/O端口值,也不需要IRQ中断号,唯一需要程序指定的是其伪硬件地址(这个硬件地址是"0ED000",ifconfig可以看到其硬件地址是 00:45:44:30:30:30,struct net_device中的dev_addr域存放网络接口的物理地址。操作ednet_open()必须调用netif_start_queue()内核 API开启网络接口接收和发送数据队列。

 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<

上一页 1 2 3 45 6 下一页

上一篇:Linux下PCI设备驱动程序开发   下一篇:ucLinux下sqlite数据库移植全攻略
文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论

   相关文章:
·从Linux BIOS的起源 看未来主板框架

   文章评论:(1条)
  
 请留名: 匿名评论   点击查看所有评论 论坛讨论
 

 声明:刊登此文章是为了传递更多信息,文章内容仅供参考,转载请注明出处。