zoukankan      html  css  js  c++  java
  • linux网络设备驱动程序

    4.linux网络设备驱动程序体系结构

         --------------------------------------
        |        数据包发送     |     数据包接收       |    ----->网络协议接口层
        |  dev_queue_xmit() |     netif_rx()       |
        |--------------------------------------
        |            结构体 net_device           |    ----->网络设备接 口层
         --------------------------------------
        |        数据包发送      |      中断处理       |    ----->网络驱动功能层
        |  hard_start_xmit() |     数据包接收       |
        |--------------------------------------
        |         网络设备媒介(物理层)           |    ----->网络设备与媒介层
         --------------------------------------

    硬件相关的驱动程序(要提供hard_start_xmit, 有数据时要用netif_rx上报)

    5.sk_buff套接字缓冲区,用于linux中各层之间传输数据。当要发送数据包的时候,内核必须建立一个包含传输数据的sk_buff
    然后将sk_buff交给下层,各层在sk_buff递交给下一层,各层在sk_buff中添加不同的协议贞头,直到交给网络设备发送。接收原理相同。
    struct sk_buff {
    /* These two members must be first. */
    struct sk_buff *next;
    struct sk_buff *prev;
    /*网络设备接口层中的net_devive结构体*/
    struct net_device *dev;
    ....

    /*控制缓冲区 ,每个层都可以使用它,用于存放私有数据*/
    char cb[48];

    unsigned int len, //数据真实长度
    data_len,//数据长度
    mac_len; //链接层帧头的长度
    /*钩子函数 垃圾回收*/
    void (*destructor)(struct sk_buff *skb);

    sk_buff_data_t transport_header;
    sk_buff_data_t network_header;
    sk_buff_data_t mac_header;
    /* These elements must be at the end, see alloc_skb() for details. */
    sk_buff_data_t tail;
    sk_buff_data_t end;
    unsigned char *head,
    *data;
    unsigned int truesize;
    atomic_t users;
    };
    5.1、sk_buff结构:
    ----------- ---->*head
    | 头部 |
    |------------ ---->*data
    | 数据 |
    | 缓存 |
    |----------- ---->*tail
    | 尾部 |
    ----------- ---->*end

    5.2、分配:
    分配套接字缓冲区:以GFP_ATOMIC优先级进行skb的分配,因为该函数经常在设备驱动中被调用
    static inline struct sk_buff *dev_alloc_skb(unsigned int length)

    分配一个套接字缓冲区和一个数据缓冲区,参数len为数据缓冲区的大小,ARM通常32位对齐,参数priority为内存分配的优先级。
    static inline struct sk_buff *alloc_skb(unsigned int size,gfp_t priority)

    5.3、释放:
    //用于释放dev_alloc_skb的内存,用于非中断上下文中
    void dev_kfree_skb(struct sk_buff *skb)
    //用于中断上下文中
    static inline void dev_kfree_skb_irq(struct sk_buff *skb)
    //中断和非中断都可以用 any,其实就是做了一个判断
    void dev_kfree_skb_any(struct sk_buff *skb)
    {
    if (in_irq() || irqs_disabled())
    dev_kfree_skb_irq(skb);
    else
    dev_kfree_skb(skb);
    }
    5.4、变更:
    缓冲区尾部增加数据 skb
    static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
    skb->tail += len;
    skb->len += len;

    缓冲区开头增加数据
    static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
    skb->data -= len;
    skb->len += len;

    缓冲区开头移除数据
    static inline unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
    skb->len -= len;
    return skb->data += len;

    调节缓冲区头部
    static inline void skb_reserve(struct sk_buff *skb, int len)
    skb->data += len;
    skb->tail += len;

    6.net_device结构体
    struct net_device
    {
    /*网络设备名称*/
    char name[IFNAMSIZ];

    unsigned long mem_end; /* 共享内存结束地址 */
    unsigned long mem_start; /* 共享内存开始地址 */
    unsigned long base_addr; /* I/O设备的基地址 */
    unsigned int irq; /* 设备中断号 */

    unsigned char if_port; /* 多端口设备使用哪一个端口*/
    unsigned char dma; /* DMA channel

    /*设备初始化函数,只被调用一次 */
    int (*init)(struct net_device *dev);

    /*用于获取网络设备的状态信息*/
    struct net_device_stats* (*get_stats)(struct net_device *dev);
    /*存放详细的网络设备流量统计信息*/
    struct net_device_stats stats;

    .......................
    unsigned mtu; /* interface MTU(最大传输单元) value*/
    unsigned short type; /* 硬件接口类型 */
    unsigned short hard_header_len; /* 硬件头的长度 */

    /*MAC地址*/
    unsigned char dev_addr[MAX_ADDR_LEN];

    /*私有数据,用于存放私有的数据,netdev_priv()*/
    void *priv;

    /*启动数据包的发送*/
    int (*hard_start_xmit) (struct sk_buff *skb,struct net_device *dev);

    /*开始发送数据时候的时间戳 格式为:jiffies */
    unsigned long trans_start;

    /* 最后一次接受数据包的长度 */
    unsigned long last_rx;

    /* open用于打开网络设备,获取所需的IO地址和中断号.stop()用于停止网络设备 */
    int (*open)(struct net_device *dev);
    int (*stop)(struct net_device *dev);


    /*用于设置设备的MAC地址*/
    int (*set_mac_address)(struct net_device *dev,void *addr);

    /*进行特定的IO控制*/
    int (*do_ioctl)(struct net_device *dev,
    struct ifreq *ifr, int cmd);
    /*用于配置接口,可以用来改变设备的IO地址和中断号*/
    int (*set_config)(struct net_device *dev,struct ifmap *map);

    /*数据包发送超时时候会被调用,可以用来重启网卡*/
    void (*tx_timeout) (struct net_device *dev);

    /*linux4.0才有的一个结构体,linux2.6没有,操作硬件的集合*/
    struct net_device_ops {
    .....
    };
    };

  • 相关阅读:
    LeetCode--011--盛最多水的容器(java)
    LeetCode--008--字符串转换整数 (atoi)(java)
    TF-IDF的解释
    Ubuntu14.04LTS下安装Node.js&NPM以及个人博客hexo的初始化配置
    UVa10791
    唯一分解定理
    UVa10375
    ubuntu下codeblocks安装与中文化
    Uva11582
    Ubuntu下使用网易云音乐
  • 原文地址:https://www.cnblogs.com/veryStrong/p/6192589.html
Copyright © 2011-2022 走看看