Linux網(wǎng)絡(luò)設(shè)備驅(qū)動程序體系結(jié)構(gòu)
--------------------------------------
? ? |? ? ? ? 數(shù)據(jù)包發(fā)送? ? |? ? 數(shù)據(jù)包接收? ? ? |? ? ----->網(wǎng)絡(luò)協(xié)議接口層
? ? |? dev_queue_xmit() |? ? netif_rx()? ? ? |
? ? |--------------------------------------
? ? |? ? ? ? ? ? 結(jié)構(gòu)體 net_device? ? ? ? ? |? ? ----->網(wǎng)絡(luò)設(shè)備接 口層
? ? --------------------------------------
? ? |? ? ? ? 數(shù)據(jù)包發(fā)送? ? ? |? ? ? 中斷處理? ? ? |? ? ----->網(wǎng)絡(luò)驅(qū)動功能層
? ? |? hard_start_xmit() |? ? 數(shù)據(jù)包接收? ? ? |
? ? |--------------------------------------
? ? |? ? ? ? 網(wǎng)絡(luò)設(shè)備媒介(物理層)? ? ? ? ? |? ? ----->網(wǎng)絡(luò)設(shè)備與媒介層
? ? --------------------------------------
硬件相關(guān)的驅(qū)動程序(要提供hard_start_xmit, 有數(shù)據(jù)時要用netif_rx上報)
5.sk_buff套接字緩沖區(qū),用于linux中各層之間傳輸數(shù)據(jù)。當(dāng)要發(fā)送數(shù)據(jù)包的時候,內(nèi)核必須建立一個包含傳輸數(shù)據(jù)的sk_buff,然后將sk_buff交給下層,各層在sk_buff遞交給下一層,各層在sk_buff中添加不同的協(xié)議貞頭,直到交給網(wǎng)絡(luò)設(shè)備發(fā)送。接收原理相同。
struct sk_buff {
?/* These two members must be first. */
?struct sk_buff *next;
?struct sk_buff *prev;
?/*網(wǎng)絡(luò)設(shè)備接口層中的net_devive結(jié)構(gòu)體*/
struct net_device *dev;
?....
/*控制緩沖區(qū) ,每個層都可以使用它,用于存放私有數(shù)據(jù)*/
char cb[48];
unsigned int len, //數(shù)據(jù)真實長度
data_len,//數(shù)據(jù)長度
mac_len; //鏈接層幀頭的長度
/*鉤子函數(shù) 垃圾回收*/
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結(jié)構(gòu):
----------- ---->*head
?| 頭部 |
?|------------ ---->*data
?| 數(shù)據(jù) |
?| 緩存 |
?|----------- ---->*tail
?| 尾部 |
----------- ---->*end
5.2、分配:
?分配套接字緩沖區(qū):以GFP_ATOMIC優(yōu)先級進(jìn)行skb的分配,因為該函數(shù)經(jīng)常在設(shè)備驅(qū)動中被調(diào)用
static inline struct sk_buff *dev_alloc_skb(unsigned int length)
分配一個套接字緩沖區(qū)和一個數(shù)據(jù)緩沖區(qū),參數(shù)len為數(shù)據(jù)緩沖區(qū)的大小,ARM通常32位對齊,參數(shù)priority為內(nèi)存分配的優(yōu)先級。
static inline struct sk_buff *alloc_skb(unsigned int size,gfp_t priority)
5.3、釋放:
//用于釋放dev_alloc_skb的內(nèi)存,用于非中斷上下文中
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、變更:
?緩沖區(qū)尾部增加數(shù)據(jù) skb
?static inline unsigned char *skb_put(struct sk_buff *skb, unsigned int len)
?skb->tail += len;
?skb->len += len;
緩沖區(qū)開頭增加數(shù)據(jù)
static inline unsigned char *skb_push(struct sk_buff *skb, unsigned int len)
?skb->data -= len;
?skb->len += len;
緩沖區(qū)開頭移除數(shù)據(jù)
static inline unsigned char *skb_pull(struct sk_buff *skb, unsigned int len)
?skb->len -= len;
?return skb->data += len;
調(diào)節(jié)緩沖區(qū)頭部
static inline void skb_reserve(struct sk_buff *skb, int len)
?skb->data += len;
?skb->tail += len;
6.net_device結(jié)構(gòu)體
struct net_device
?{
?/*網(wǎng)絡(luò)設(shè)備名稱*/
char name[IFNAMSIZ];
unsigned long mem_end; /* 共享內(nèi)存結(jié)束地址 */
unsigned long mem_start; /* 共享內(nèi)存開始地址 */
unsigned long base_addr; /* I/O設(shè)備的基地址 */
unsigned int irq; /* 設(shè)備中斷號 */
unsigned char if_port; /* 多端口設(shè)備使用哪一個端口*/
unsigned char dma; /* DMA channel
/*設(shè)備初始化函數(shù),只被調(diào)用一次 */
int (*init)(struct net_device *dev);
/*用于獲取網(wǎng)絡(luò)設(shè)備的狀態(tài)信息*/
struct net_device_stats* (*get_stats)(struct net_device *dev);
?/*存放詳細(xì)的網(wǎng)絡(luò)設(shè)備流量統(tǒng)計信息*/
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];
/*私有數(shù)據(jù),用于存放私有的數(shù)據(jù),netdev_priv()*/
?void *priv;
/*啟動數(shù)據(jù)包的發(fā)送*/
int (*hard_start_xmit) (struct sk_buff *skb,struct net_device *dev);
/*開始發(fā)送數(shù)據(jù)時候的時間戳 格式為:jiffies */
?unsigned long trans_start;
/* 最后一次接受數(shù)據(jù)包的長度 */
unsigned long last_rx;
/* open用于打開網(wǎng)絡(luò)設(shè)備,獲取所需的IO地址和中斷號.stop()用于停止網(wǎng)絡(luò)設(shè)備 */
int (*open)(struct net_device *dev);
?int (*stop)(struct net_device *dev);
?/*用于設(shè)置設(shè)備的MAC地址*/
int (*set_mac_address)(struct net_device *dev,void *addr);
/*進(jìn)行特定的IO控制*/
int (*do_ioctl)(struct net_device *dev,
?struct ifreq *ifr, int cmd);
?/*用于配置接口,可以用來改變設(shè)備的IO地址和中斷號*/
int (*set_config)(struct net_device *dev,struct ifmap *map);
/*數(shù)據(jù)包發(fā)送超時時候會被調(diào)用,可以用來重啟網(wǎng)卡*/
void (*tx_timeout) (struct net_device *dev);
/*linux4.0才有的一個結(jié)構(gòu)體,linux2.6沒有,操作硬件的集合*/
struct net_device_ops {
?.....
?};
?};
?
評論
查看更多