浅谈 Linux 内核无线子系统(2)

图一所示中,存在两条主要路径:数据路径和管理路径。数据路径对应 IEEE802.11 数据帧,而管理路径对应着控制帧。
在 IEEE802.11 的控制帧中,大部分用于如 ACK 这类时间紧急的操作,并且一般直接由硬件实现。一个例外可能就是 PS-Poll 帧(用于 Power Save 控制),它也可以由 mac80211 实现。
数据和管理路径在 mac80211 里面是分开实现的。

4 数据包是如何被发送?

接下来,我们集中探讨下数据的发送过程。
首先,数据包起源于用户空间的应用程序,应用程序首先创建一个套接字,然后绑定一个接口(如,以太网接口、 WiFi 接口)。
接下来将数据写入到套接字缓冲区,最后再将缓冲区的数据发送出去。在套接字创建时,我们需要指明将要使用的协议族,这将在内核中起作用。
刚才这些发生在图一中的 Data Application 模块中,最终应用程序陷入系统调用,随后在内核空间进行接下来的工作。

数据的传输首先经过套接字层,这个过程中一个最重要的数据结构就是 sk_buff ,一般称为 skb 。一个 skb 结构中的成员包含着缓冲区的地址以及数据长度。
它还为内核中不同层对数据的操纵提供了良好的支持;实现了众多的接口,如,不同网络层首部的插入与去除等。整个数据的发送/接收过程均会用到这个结构。

我们跳过网络协议模块,对于网络协议我没有太多想说的,因为一旦涉及网络协议,简直说不尽道不完。在这里协议并不是我们主要关心的。
不过我们需要知道的是,数据传输使用的协议在套接字创建的时候就与指定的协议绑定了,然后相关的协议便会负责相关层的数据传输。

接下来,数据由网络层落到了设备无关层。这一层透明的连接着各种各样的硬件设备(如以太网设备、 WiFi 设备等)。
设备无关层一个重要的结构是: net_device 。我们回去看图一,再看接下来的代码就能解释内核是如何与以太网设备驱动通信的。
具体接口通过 net_device_ops 结构实现,该结构对应了 net_device 的很多操作。
如下是 net_device_ops 结构的部分成员:

struct net_device_ops { int (*ndo_init)(struct net_device *dev); void (*ndo_uninit)(struct net_device *dev); int (*ndo_open)(struct net_device *dev); int (*ndo_stop)(struct net_device *dev); netdev_tx_t (*ndo_start_xmit)(struct sk_buff *skb, struct net_device *dev); netdev_features_t (*ndo_features_check)(struct sk_buff *skb, struct net_device *dev, netdev_features_t features); u16 (*ndo_select_queue)(struct net_device *dev, struct sk_buff *skb, void *accel_priv, select_queue_fallback_t fallback); void (*ndo_change_rx_flags)(struct net_device *dev, int flags); void (*ndo_set_rx_mode)(struct net_device *dev); int (*ndo_set_mac_address)(struct net_device *dev, void *addr); int (*ndo_validate_addr)(struct net_device *dev); int (*ndo_do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); int (*ndo_set_config)(struct net_device *dev, struct ifmap *map); int (*ndo_change_mtu)(struct net_device *dev, int new_mtu); int (*ndo_neigh_setup)(struct net_device *dev, struct neigh_parms *); void (*ndo_tx_timeout) (struct net_device *dev); struct rtnl_link_stats64* (*ndo_get_stats64)(struct net_device *dev, struct rtnl_link_stats64 *storage); struct net_device_stats* (*ndo_get_stats)(struct net_device *dev); int (*ndo_vlan_rx_add_vid)(struct net_device *dev, __be16 proto, u16 vid); int (*ndo_vlan_rx_kill_vid)(struct net_device *dev, ... ... };

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/14982.html