• 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 {
    .....
    };
    };

  • 相关阅读:
    yii 引入文件
    CodeForces 621C Wet Shark and Flowers
    面试题题解
    POJ 2251 Dungeon Master
    HDU 5935 Car(模拟)
    HDU 5938 Four Operations(暴力枚举)
    CodeForces 722C Destroying Array(并查集)
    HDU 5547 Sudoku(dfs)
    HDU 5583 Kingdom of Black and White(模拟)
    HDU 5512 Pagodas(等差数列)
  • 原文地址:https://www.cnblogs.com/veryStrong/p/6192589.html
Copyright © 2020-2023  润新知