1、linux目前支持多种协议族,每个协议族用一个net_porto_family结构实例来表示,在初始化时,会调用sock_register()函数初始化注册到net_families[NPROTO]中去;
同时出现了一个地址族的概念,目前协议族和地址族是一 一 对应关系。历史上曾经有一个协议族支持多个地址族,实际上从未实现过。在socket.h文件中PF_XX和AF_XX 值一样
2、由于不同协议族的结构差别很大,为了封装统一,以便在初始化时,可以统一接口,于是就有了net_proto_family。其用sock_register统一注册,初始化钩子,具体初始化,其实现见钩子实现,类似于VFS 的实现方式。一种很好的设计思想。
/*ops->create在应用程序创建套接字的时候,引起系统调用,从而在函数__sock_create中执行ops->create netlink为netlink_family_ops 应用层创建套接字的时候,内核系统调用sock_create,然后执行该函数 pf_inet的net_families[]为inet_family_ops,对应的套接口层ops参考inetsw_array中的inet_stream_ops inet_dgram_ops inet_sockraw_ops, 传输层操作集分别为tcp_prot udp_prot raw_prot netlink的net_families[]netlink_family_ops,对应的套接口层ops为netlink_ops family协议族通过sock_register注册 传输层接口tcp_prot udp_prot netlink_prot等通过proto_register注册 IP层接口通过inet_add_protocol(&icmp_protocol等注册 ,这些组成过程参考inet_init函数*/
struct net_proto_family {//操作集参考inetsw_array
int family;
int (*create)(struct net *net, struct socket *sock,
int protocol, int kern);协议族的套接字创建函数指针,每个协议族实现都不同
struct module *owner;
};
Internet 协议族的net_proto_family结构实例为inet_family_ops,创建套接字socket时,其调用接口为inet_create().
2、inet_protosw 结构
/* This is used to register socket interfaces for IP protocols. */
struct inet_protosw {
struct list_head list;/* 初始化时将相同的type的inet_protosw散列在同一个链表*/
/* These two fields form the lookup key. */
unsigned short type; /* This is the 2nd argument to socket(2). 表示套接口字的类型,对于Internet 协议族有三种类型 SOCK_STREAM SOCK_DGRAM SOCK_RAW 对于与应用层socket函数的第二个参数type*/
unsigned short protocol; /* This is the L4 protocol number. */
struct proto *prot; /*套接口网络层口,tcp为tcp_port udp为udp_port 原始套接字为raw_port*/
const struct proto_ops *ops;/* 套接口传输层接口,tcp为inet_stream_ops,udp 为inet_dgram_ops,原始套接字为inet_sockraw_ops*/
unsigned char flags; /* See INET_PROTOSW_* below. */
};
#define INET_PROTOSW_REUSE 0x01 /* Are ports automatically reusable? 端口重用*/ #define INET_PROTOSW_PERMANENT 0x02 /* Permanent protocols are unremovable. 协议不能被替换卸载*/ #define INET_PROTOSW_ICSK 0x04 /* Is this an inet_connection_sock? 是不是为连接类型的接口*/