lwip源码分析1------综述及设备驱动层

来源:互联网 发布:麦克风淘宝购买 编辑:程序博客网 时间:2024/05/16 15:34

http://blog.chinaunix.net/uid-9863638-id-1996356.html

Lwip学习笔记1

2010-1-4 2010-1-8

Written by leeming       leeming.cublog.cn

1.tcpip一般的实现方式有:

●每一层一个进程,网络接口层,ip层,tcp层,应用程序层,这个方法的好处是各层之间结构清晰明了,容易阅读和调试,但是这种分层思想带来的通病就是效率低下,如果按照这种实现方式即上层应用接受一个数据包,要通过网络接口层进程->ip层进程->tcp层进程->应用程序层进程,这种效率是不能接受的。

Tcpip协议栈处于内核态,属于操作系统内核的一部分,同属于内核进程,应用程序通过系统调用来和协议层通信,这样的好处就是协议层之间不需要耗时的频繁的协议间进程切换,但是这种方式只是在一些比较高级的操作系统中实现(至少要到虚拟内存管理mmu),比如windowslinux就是采用这种方式的。

●lwip采用了另外一种方式,它也是将协议层全部在一个进程中实现的,应用程序可以在协议层进程中实现(即利用lwip自己提供的一套内部回调函数来通信)也可以通过另外一个进程实现,如果应用程序另起一个进程的话则需要通过操作系统提供的进程间通信的机制(管道,邮箱等)来实现交互。这种方式就带有相当的灵活性,而且由于对应用程序的进程没有特殊限制,一般的操作系统都能支持。
 
 

整个学习的过程也打算按照这种流程来学习,先从底层看起(这部分也是我最熟悉的),依次从network interface layer -> internetwork layer -> transport layer -> application layer(这也是按照tcpip的经典四层分法的)。

 

 

首先来看网络接口层:

这一层的主要文件位于/src/netif目录,主要是网络设备驱动文件(一个skeleton程序),一个loopback文件(非常简单),arp模块,ppp协议栈。核心的netif的通用程序在/src/core目录下。

1.         重要的结构体有:

Struct netif

{

       ……

}

这个结构体相当linux中的net_device结构体,用lwip的原文来说就是整个网络接口层中都会用到的一个结构体,对于理解这一层非常重要。

具体看一下:

struct netif {

  /*指向链表中下一个网络接口的指针 */

  struct netif *next;

 

  /** IP address configuration in network byte order */

  struct ip_addr ip_addr;

  struct ip_addr netmask;

  struct ip_addr gw;

 

  /*这个函数是设备驱动调用用来向tcpip协议层传递数据包*/

  err_t (* input)(struct pbuf *p, struct netif *inp);

  /*这个函数是当ip层想向网络接口层发送一个数据包时调用,一般会先将ip地址解析为mac地址,然后发送 */

  err_t (* output)(struct netif *netif, struct pbuf *p,struct ip_addr *ipaddr);

 

  /*这个函数是当arp模块需要向接口层发送数据包时被调用, */

  err_t (* linkoutput)(struct netif *netif, struct pbuf *p);

 

……

  /*用来指向设备的独有的一些信息,类似linux中常用的void * private. */

  void *state;

#if LWIP_DHCP

  /*这个netifdhcp信息 */

  struct dhcp *dhcp;

#endif /* LWIP_DHCP */

#if LWIP_AUTOIP

  /** the AutoIP client state information for this netif */

  struct autoip *autoip;

#endif

#if LWIP_NETIF_HOSTNAME

  /* the hostname for this netif, NULL is a valid value */

  char*  hostname;

#endif /* LWIP_NETIF_HOSTNAME */

 

  /*最大传送字节数,以太网一般是1500个字节(术语应该叫八位组) */

  u16_t mtu;

  /*硬件地址长度,对于以太网就是mac地址长度,一般为6个字节 */

  u8_t hwaddr_len;

  /*mac地址 */

  u8_t hwaddr[NETIF_MAX_HWADDR_LEN];

  /** flags (see NETIF_FLAG_ above) */

  u8_t flags;

  /** descriptive abbreviation */

  char name[2];

  /** number of this interface */

  u8_t num;

 

……

 

#if LWIP_IGMP

  /*这个函数在添加或者删除mac地址的多播路由表时被调用*/

  err_t (*igmp_mac_filter)( struct netif *netif, struct ip_addr *group, u8_t action);

#endif /* LWIP_IGMP */

#if LWIP_NETIF_HWADDRHINT

  u8_t *addr_hint;

#endif /* LWIP_NETIF_HWADDRHINT */

#if ENABLE_LOOPBACK

  /* List of packets to be queued for ourselves. */

  struct pbuf *loop_first;

  struct pbuf *loop_last;

#if LWIP_LOOPBACK_MAX_PBUFS

  u16_t loop_cnt_current;

#endif /* LWIP_LOOPBACK_MAX_PBUFS */

#endif /* ENABLE_LOOPBACK */

};

 

linux中的网络驱动一样,主要的工作还是补充netif这个网络接口层最重要的结构体,相应的函数自然是收发包的Inputoutput函数,还有就是arplinkoutput函数。