1.选择路由
若要将数据包发至PC2,则Linux系统通过查询路由表可知168.1.1.10(目的地址)的网关地址为192.168.1.1,此时Linux系统选择网卡1发送数据包。
2.邻居子系统(通过arp协议建立起邻居的信息)
选择网卡1发送数据时,首先将数据包发给邻居(网关),再由邻居转发至后面,若要发送给邻居,则必须知道邻居的MAC地址,若不知道邻居的MAC地址,则需要通过arp请求包获取邻居的MAC地址。
Linux网络体系结构由以下五个部分组成 1)系统调用接口 2)协议无关接口 3)网络协议 4)设备无关接口 5 设备驱动程序。下面分别简述五个部分:
1)系统调用接口系统调用接口是用户空间的应用程序正常访问内核的唯一合法途径(终端和陷入也可访问内核)。如:
asmlingkage long sys_getpid(void)
{
return current->pid;
}
系统调用一般由sys开头 ,前面的修饰符是asmlingkage,表示函数由堆栈获得参数。
2)协议无关接口协议无关接口是由socket来实现的。它提供了一组通用函数来支持各种不同协议。
通过网络栈进行的通信都需要对 socket 进行操作。Linux 中的 socket 结构是 struct sock ,这个结构是在 linux/include/net/sock.h 中定义的。这个巨大的结构中包含了特定 socket 所需要的所有状态信息,其中包括 socket 所使用的特定协议和在 socket 上可以执行的一些操作。
网络子系统可以通过一个定义了自己功能的特殊结构来了解可用协议。每个协议都维护了一个名为 proto 的结构(可以在 linux/include/net/sock.h 中找到)。这个结构定义了可以在从 socket 层到传输层中执行特定的 socket 操作
3)网络协议Linux支持多种网络协议,可以在<linux/socket.h>中查到所支持的网络协议:
#define AF_UNIX 1 /* Unix domain sockets */
#define AF_LOCAL 1 /* POSIX name for AF_UNIX */
#define AF_INET 2 /* Internet IP Protocol */
#define AF_AX25 3 /* Amateur Radio AX.25 */
#define AF_IPX 4 /* Novell IPX
… …
其中每一个所支持的协议对应net_family[]数组中的一项,net_family[]是结构体指针数组,其中的每一项都是一个结构体指针,指向一个net_proto_family 结构
struct net_proto_family {
int family;
int (*create) (struct socket * sock, int protocol);
short authentication;
short encryption;
short encrypt_net;
struct module *owner;
};这个结构体中注册了关于协议的信息。
4)设备无关接口设备无关接口是由net_device实现的。任何设备和上层通信都是通过net_device设备无关接口。
它将协议与具有很多各种不同功能的硬件设备连接在一起。这一层提供了一组通用函数供底层网络设备驱动程序使用,让它们可以对高层协议栈进行操作。
首先,设备驱动程序可能会通过调用 register_netdevice 或 unregister_netdevice 在内核中进行注册或注销。调用者首先填写 net_device 结构,然后传递这个结构进行注册。内核调用它的 init 函数(如果定义了这种函数),然后执行一组健全性检查,并创建一个 sysfs 条目,然后将新设备添加到设备列表中(内核中的活动设备链表)。在 linux/include/linux/netdevice.h 中可以找到这个 net_device 结构。这些函数都是在 linux/net/core/dev.c 中实现的。
要从协议层向设备中发送 sk_buff ,就需要使用 dev_queue_xmit 函数。这个函数可以对 sk_buff 进行排队,从而由底层设备驱动程序进行最终传输(使用 sk_buff 中引用的 net_device 或 sk_buff->dev 所定义的网络设备)。dev 结构中包含了一个名为 hard_start_xmit 的方法,其中保存有发起 sk_buff 传输所使用的驱动程序函数。
报文的接收通常是使用 netif_rx 执行的。当底层设备驱动程序接收一个报文(包含在所分配的 sk_buff 中)时,就会通过调用 netif_rx 将 sk_buff 上传至网络层。然后,这个函数通过 netif_rx_schedule 将 sk_buff 在上层协议队列中进行排队,供以后进行处理。可以在 linux/net/core/dev.c 中找到 dev_queue_xmit 和 netif_rx 函数。
5)设备驱动程序网络栈底部是负责管理物理网络设备的设备驱动程序。例如,包串口使用的 SLIP 驱动程序以及以太网设备使用的以太网驱动程序都是这一层的设备。