diff --git "a/2024/02/27/Linux\351\251\261\345\212\250\345\274\200\345\217\221/index.html" "b/2024/02/27/Linux\351\251\261\345\212\250\345\274\200\345\217\221/index.html" index 0351a9f..67ec2d3 100644 --- "a/2024/02/27/Linux\351\251\261\345\212\250\345\274\200\345\217\221/index.html" +++ "b/2024/02/27/Linux\351\251\261\345\212\250\345\274\200\345\217\221/index.html" @@ -38,7 +38,7 @@ - + @@ -1422,6 +1422,21 @@

libusb

+

linux网络设备驱动框架

net_device结构体

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
struct net_device {
//网络设备的操作集合函数,包含了一系列网络设备操作回调函数,类似字符设备种的file_operations.
const struct net_device_ops *netdev_ops;file_operations.
//头部相关的操作集,比如创建解析缓冲等
const struct header_ops *header_ops;
// 发送队列
struct netdev_queue *_tx;
netdev_features_t gso_partial_features;
//当前有效发送队列数量
unsigned int real_num_tx_queues;
//网络最大传输单元
unsigned int mtu;
//网络接口标志
unsigned int flags;
//当前活动队列数量
unsigned int real_num_rx_queues;
//接收队列
rx_handler_func_t __rcu *rx_handler;
//全局网络设备链表
struct list_head dev_list;
//napi网络设备列表入口
struct list_head napi_list;
//注销的网络设备列表入口
struct list_head unreg_list;
//关闭的网络设备列表入口
struct list_head close_list;
//用于指定ARP模块的类型
unsigned short type;
//指定接口的端口类型,如果支持多端口的话就通过if_port来指定所使用的端口类型
unsigned char if_port;
//网络设备所使用的DMA通道,不是所有的设备都会用到DMA
unsigned char dma;

/* Interface address info. */
//永久硬件地址
unsigned char perm_addr[MAX_ADDR_LEN];
unsigned char addr_assign_type;
//硬件地址长度
unsigned char addr_len;
//设备中断号
int irq;
//接收队列数量
unsigned int num_rx_queues;
//对应的phy设备
struct phy_device *phydev;
};
+ + + + + +

net_device_ops:

+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
struct net_device_ops {
//当第一次注册网络设备的时候此函数会执行,设备可以在此函数种做一些需要退后初始化的内容,不过一般驱动中不使用此函数,虚拟网络设备可能会使用
int (*ndo_init)(struct net_device *dev);
//卸载网络设备的时候此函数会执行
void (*ndo_uninit)(struct net_device *dev);
//打开网络设备的时候此函数会执行,网络驱动程序需要实现此函数,非常重要,会做一些初始化操作如,使能网络外设时钟,申请环形缓冲区,初始化MAC外设,绑定对应的PHY,使能napi模块,开启PHY,使能传输队列
int (*ndo_open)(struct net_device *dev);
//关闭网络设备的时候此函数会执行,释放资源
int (*ndo_stop)(struct net_device *dev);
//当需要发送数据的时候此函数就会执行,此函数有一个=参数为sk_buff结构体指针,sk_buff结构体在linux网络驱动中十分重要,sk_buff保存了上层传递给网络驱动层的数据。也就是说,要发送出去的数据都存在了sk_buff中,如果发送成功此函数返回NETDEV_TX_OK失败返回NETDEV_TX_BUSY
netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb,
struct net_device *dev);
//当设备支持多传输队列的时候选择哪个队列
u16 (*ndo_select_queue)(struct net_device *dev,
struct sk_buff *skb,
struct net_device *sb_dev);
//此函数用于改变地址过滤链表,根据net_device的flags成员变量来设置SOC网络外设寄存器。比如flags可能为IFF_PROMISC,IFF_ALLMULTI或IFF_MULTICAST分别表示混杂模式,单播模式或多播模式
void (*ndo_set_rx_mode)(struct net_device *dev);
//此函数用于修改网卡的MAC地址,设置net_device的dev_addr成员变量,并且将MAC地址写入到网络外设的硬件寄存器中。
int (*ndo_set_mac_address)(struct net_device *dev,
void *addr);
//验证MAC地址是否合法,也就是验证net_device的dev_addr中的MAC地址是否合法
int (*ndo_validate_addr)(struct net_device *dev);
//用户程序调用ioctl的时候此函数就会执行,比如PHY芯片相关的命令操作,一般会直接调用phy_mii_ioctl函数
int (*ndo_do_ioctl)(struct net_device *dev,
struct ifreq *ifr, int cmd);
//更改MTU大小
int (*ndo_change_mtu)(struct net_device *dev,
int new_mtu);
//当发送超时的时候函数会执行,一般都是网络出问题导致发送超时,一般可能会重启MAC和PHY,重新开始数据发送等
void (*ndo_tx_timeout) (struct net_device *dev,
unsigned int txqueue);
//使用查询的方式来处理网卡数据的收发
void (*ndo_poll_controller)(struct net_device *dev);
//修改net_device的features属性,设置相应的硬件属性
int (*ndo_set_features)(struct net_device *dev,

};
+ + + + + +

napi:
Linux 里面的网络数据接收也轮询和中断两种,中断的好处就是响应快,数据量小的时候处理及时,速度快,但是一旦当数据量大,而且都是短帧的时候会导致中断频繁发生,消耗大量的 CPU 处理时间在中断自身处理上。轮询恰好相反,响应没有中断及时,但是在处理大量数据的时候不需要消耗过多的 CPU 处理时间。 Linux 在这两个处理方式的基础上提出了另外一种网络数据接收的处理方法: NAPI(New API), NAPI 是一种高效的网络处理技术。NAPI 的核心思想就是不全部采用中断来读取网络数据,而是采用中断来唤醒数据接收服务程序,在接收服务程序中采用 POLL 的方法来轮询处理数据。这种方法的好处就是可以提高短数据包的接收效率,减少中断处理的时间。

@@ -1570,7 +1585,7 @@

-
  1. 1. 字符设备驱动开发基础实验
  2. 2. 第一个Linux驱动实验
  3. 3. LED驱动实验(直接操作寄存器版)
  4. 4. Linux新字符设备驱动实验
  5. 5. Linux设备树
    1. 5.1. dts基本语法
    2. 5.2. 设备树在系统里面的体现
  6. 6. Linux内核的OF操作函数
  7. 7. pinctl和gpio子系统
  8. 8. beep蜂鸣器实验
  9. 9. linux并发与竞争
  10. 10. 按键输入实验(直接读io)
  11. 11. linux内核定时器实验
  12. 12. linux中断实验
    1. 12.0.1. 下半部要做的事情太多并且很复杂:工作队列:
  • 13. linux阻塞和非阻塞实验
  • 14. linux异步通知实验
  • 15. plantform设备驱动实验
  • 16. linux自带led驱动
  • 17. linux杂项misc驱动实验
  • 18. linux INPUT子系统驱动实验
  • 19. linux lcd驱动实验
  • 20. linux RTC驱动实验
  • 21. linux iic驱动实验
  • 22. linux SPI驱动实验
    1. 22.1. 编写SPI设备驱动程序
  • 23. linux 多点电容屏触摸实验
  • 24. USB驱动
  • +
    1. 1. 字符设备驱动开发基础实验
    2. 2. 第一个Linux驱动实验
    3. 3. LED驱动实验(直接操作寄存器版)
    4. 4. Linux新字符设备驱动实验
    5. 5. Linux设备树
      1. 5.1. dts基本语法
      2. 5.2. 设备树在系统里面的体现
    6. 6. Linux内核的OF操作函数
    7. 7. pinctl和gpio子系统
    8. 8. beep蜂鸣器实验
    9. 9. linux并发与竞争
    10. 10. 按键输入实验(直接读io)
    11. 11. linux内核定时器实验
    12. 12. linux中断实验
      1. 12.0.1. 下半部要做的事情太多并且很复杂:工作队列:
  • 13. linux阻塞和非阻塞实验
  • 14. linux异步通知实验
  • 15. plantform设备驱动实验
  • 16. linux自带led驱动
  • 17. linux杂项misc驱动实验
  • 18. linux INPUT子系统驱动实验
  • 19. linux lcd驱动实验
  • 20. linux RTC驱动实验
  • 21. linux iic驱动实验
  • 22. linux SPI驱动实验
    1. 22.1. 编写SPI设备驱动程序
  • 23. linux 多点电容屏触摸实验
  • 24. USB驱动
  • 25. linux网络设备驱动框架