标签:socket lamp 添加 com ret Owner mes user 参数
在Linux里面,可通过创建Socket,使得进程之间进行网络通信,可通过TCP或者UDP的方式进行交互。
scoket系统调用主要完成socket的创建,必要字段的初始化,关联传输控制块,绑定文件等任务,完成返回socket绑定的文件描述符;
/** * socket函数调用关系 * sys_socket * |-->sock_create * | |-->__sock_create * | |-->inet_create * |-->sock_map_fd */
sock_create(family, type, protocol, &sock)
在这个第一层函数sock_create里, 比起socket系统调用来多出来第四个参数&sock,
这个参数是一个结构体, 定义如下:
struct socket { socket_state state; kmemcheck_bitfield_begin(type); short type; kmemcheck_bitfield_end(type); unsigned long flags; struct socket_wq __rcu *wq; struct file *file; struct sock *sk; const struct proto_ops *ops; };
其中:
sock_create向下调到第二层方法:
__sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
这一层函数引入了一个新的参数struct net, 后面再做分析。
在__sock_create这一层:
通过调用container_of宏, 使用inode结构取到了socket结构, 返回.
全局net_families数组是一个维护着系统全局所有网络簇信息的一个数组结构.
net_families数组通过sock_register/sock_unregister添加/删除元素. ( 最多40个元素, 可以理解为下层协议的数据结构, 例如ipv4, ipv6, netlink, appletalk, bluetooth等, 本文后面部分采用ipv4作为示例. )
sock_register/sock_unregister通常在net/xxx/Af_xxx.c中调用.
例如对于INET, 在net/ipv4/Af_inet.c中将INET的struct net_proto_family结构添加到全局net_families数组中.
INET的struct net_proto_family定义如下:
static const struct net_proto_family inet_family_ops = { .family = PF_INET, .create = inet_create, .owner = THIS_MODULE, };
注意:
inetsw是一个链表数组, key为SOCK_STREAM, SOCK_DGRAM, SOCK_RAW等等.
inetsw的初始化在net/ipv4/Af_inet.c的inet_init方法中:
先初始化inesw为SOCK_STREAM/SOCK_DGRAM/SOCK_RAW等作为key的list_head数组;
遍历inetsw_array, 将其挂入inetsw中.
inetsw_array的元素封装了TCP, UDP, PING, RAW等协议, 即为上文中描述的”对应到protocol的结构体”.
inetsw_array的元素结构如下:
static struct inet_protosw inetsw_array[] = { { .type = SOCK_STREAM, .protocol = IPPROTO_TCP, .prot = &tcp_prot, .ops = &inet_stream_ops, .no_check = 0, .flags = INET_PROTOSW_PERMANENT | INET_PROTOSW_ICSK, } ... }
3 将”对应到protocol的结构体”的ops赋给struct socket结构的ops.
例如如果type是SOCK_STREAM, protocol是TCP, 将&inet_stream_ops赋给struct socket结构的ops.
各个数据结构关系如下图:
从函数原型上可以看出, 是借助struct socket来初始化网络层核心数据结构struct sock:
例如对于TCP, backlog_rcv指向net/ipv4/Tcp_ipv4.c的全局结构体struct proto tcp_prot中的tcp_v4_do_rcv
意味着该protocol允许并且已经在socket创建时指定local Port, 于是调用sk->sk_prot->hash(sk).
例如对于TCP, hash()指向net/ipv4/Tcp_ipv4.c的全局结构体struct proto tcp_prot中的inet_hash:
该方法按local Port计算hash key, 在&tcp_hashinfo->listening_hash按hash key, 将struct sock插入tcp的listening_hash链表.
但是似乎这个hashtable元素只有32个, 为什么这么小? (待看)
注意: TCP层有自己的数据结构struct tcp_sock, 从struct sock强转而来(下图图示中”tcp_sock specified”部分为struct tcp_sock的专有数据, 内存布局于common字段的后面, 故可以使用强制类型转换于struct sock互转)
至此pf->create调用结束, 也就是inet_create方法调用结束.
图示如下:
至此__sock_create调用结束.
至此socket系统调用中sock_create调用结束.
将struct socket的file设为struct file;
将struct file的private_data设为struct socket;
这样struct socket和struct file便互相关联起来了.
至此, 整个socket系统调用结束.
标签:socket lamp 添加 com ret Owner mes user 参数
原文地址:https://www.cnblogs.com/lambdoor/p/12069907.html