linux网络体系结构

来源:互联网 发布:c语言音乐点播制作 编辑:程序博客网 时间:2024/06/06 17:38

linux协议栈层次---

osi模型(open systems interconnection)但是linux中网络栈的介绍一般分为四层的internet模型。











要从协议层向设备发送数据,需要使用dev_queue_xmit函数,这个函数对数据进行排队,并交由底层设备驱动程序进行最终传输,报文的接收通常是使用netif_re执行的。当底层设备驱动程序接收到一个报文(包含在所分配的sk_buff中)时,就会通过调用netif_rx_chedule将sk_buff在上层协议队列中进行排队,供以后进行处理。

驱动程序---
网络体系结构的最底部是负责管理物理网络设备的设备驱动程序层。

linux网卡设备描述----

每个网络接口都由一个net_device结构来描述,该结构可使用如下内核函数动态分配:

1struct net_device *alloc_netdev
(
int sizeof_piv,私有数据区大小
const char *mask,设备名
void (*setup)(struct net_device *)初始化函数
)

2--struct net_device *alloc_echerdev(int sizeof_priv)
两个函数的关系???

struct net_device的主要成员包括:

    char            name[IFNAMSIZ];
    设备名如eth%d内核自动分配
    
    unsigned long        state;
    设备状态

     unsigned long base_addr
    I/O基地址

    unsigned int        irq;        
    中断号

初始化函数---
int (*init)(struct net_device *dev)
该函数在register_netdev时被调用,完成对net_device结构初始化


基本方法-----

int (*open) (struct net_device *dev)
打开接口,ficonfig激活时,接口将被打开。

int (*stop) (struct net_device *dev)
停止接口

int (*hard_start_xmit) (struct sk_buff *skb,struct net_device *dev)
数据发送函数

可选操作-----

int (*do_ioctl) (struct net_device *dev,struct ifreq *ifr,int cmd)
处理特定接口的ioctl命令

int (*set_mac_address) (struct net_device *dev, void *addr)
改变mac地址的函数,需要硬件支持该功能。

设备注册----
网络接口驱动的注册方式与字符驱动不同之处在于它没有主次设备号,并使用如下函数注册。
int register_netdev(struct net_device *dev)

sk_buff

linux内核中的每个网络数据包都由一个套接字缓冲区结构struct sk_buff描述,即一个sk_buff结构就是一个包,指向sk_buff的指针通常被称作skb。

struct sk_buff 包含的重要成员:
  
    struct net_device    *dev;处理该包的设备
    _u32 saddr;IP源地址
    _u32 daddr;IP目的地址
    _u32 raddr;IP路由器地址
     
    unsigned char *head,分配空间的开始
    unsigned char *data;有效数据的开始
    unsigned char *tail;有效数据的结束
    unsigned char *end;分配空间的结束
    unsigned long len;有效数据的长度

skb操作函数-----

struct sk_buff *alloc_skb(unsigned int len, int priority)
分配一个sk_buff结构,供协议栈代码使用

struct sk_buff *dev_alloc_skb(unsigned int len)
分配一个sk_buff结构,供驱动代码使用

unsigned char *skb_push(struct sk_buff *skb,int len)
向后移动skb的tail指针,并返回tail移动之前的值。

unsigned char *skb_put(struct sk_buf *skb,int len)
向前移动skb的head指针,并返回head移动之后的值。

kfree_skb(struct sk_buff *skb)
释放一个sk_buff结构,供协议栈代码使用

dev_kfree_skb(struct sk_buff *skb)
释放一个sk_buff结构,供驱动代码使用。

设备打开
open请求任何它需要的系统资源并且启动接口:
注册中断,dma等。
设置寄存器,启动设备。
启动发送队列。

设备打开一个列子
int net_open(struct net _device *dev)
{
申请中断
request_irq(dev->irq,&net_interrupt,SA_SHIRQ,"dm9000",dev);
设置寄存器,启动设备
。。。。。。。。。。。
启动发送队列
netif_start_queue(dev);


}

数据发送---
当核心需要发送一个数据包时,它调用hard_start_transmit函数,该函数将最终调用到net_device结构中的hard_start_xmit函数指针。

数据接收---
网络接口驱动可以实现两种方式的报文接收
中断和查询,linux中驱动多采用中断方式。

数据接收流程
1分配skb
skb=dev_alloc_skb(pkt->datalen+2)
2从硬件中读取数据到skb
3调用netif_rx将数据交给协议栈
netif_rx(skb)

中断处理
网络接口通常支持3种类型的中断:
新报文到达中断报文发送完成中断,和出错中断。中断处理程序可通过查看网卡中的中断寄存器,来分辨出中断的类型



总结------
两个重要的结构
sk_buff
net_device

原创粉丝点击