Linux socket 层处于应用层与协议层之间,为应用层提供访问接口,对协议层进行抽象,屏蔽各协议间的差异。
数据结构
struct socket {
socket_state state;
short type;
unsigned long flags;
struct file *file;
struct sock *sk;
const struct proto_ops *ops;
struct socket_wq wq;
};
sk:指向协议层sock
ops: 协议相关的一组操作集
file: 将socket与文件系统关联起来。
应用层接口
共有20个系统调用接口,下面列出其中部分
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
SYSCALL_DEFINE2(listen, int, fd, int, backlog)
SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,int __user *, upeer_addrlen)
SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,int, addrlen)
SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,unsigned int, flags, struct sockaddr__user *, addr,int, addr_len)
SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,unsigned int, flags)
SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,unsigned int, flags, struct sockaddr __user *, addr,int __user *, addr_len)
SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,unsigned int, flags)
SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,char __user *, optval, int, optlen)
SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,char __user *, optval, int __user *, optlen)
协议层接口
int sock_register(const struct net_proto_family *ops)
void sock_unregister(int family)
各协议簇(AF_INET/AF_INET6/AF_UNIX….)初始化时,会通过sock_register注册 struct net_proto_family结构体,其定义如下:
struct net_proto_family {
int family;
int (*create)(struct net *net, struct socket *sock,
int protocol, int kern);
struct module *owner;
};
如AF_INET协议簇定义:
static const struct net_proto_family inet_family_ops = {
.family = PF_INET,
.create = inet_create,
.owner = THIS_MODULE,
};
这些struct net_proto_family结构体最终保存在如下数组里,在创建SOCKET时,根椐family参数选择对应的create函数。
Socket Layer初始化
static int __init sock_init(void)
{
#Initialize the network sysctl infrastructure.
err = net_sysctl_init();
if (err)
goto out;
/*
* Initialize skbuff SLAB cache
*/
skb_init();
/*
* Initialize the protocols module.
*/
init_inodecache();
err = register_filesystem(&sock_fs_type);
if (err)
goto out;
sock_mnt = kern_mount(&sock_fs_type);
if (IS_ERR(sock_mnt)) {
err = PTR_ERR(sock_mnt);
goto out_mount;
}
/* The real protocol initialization is performed in later initcalls.
*/
#ifdef CONFIG_NETFILTER
err = netfilter_init();
if (err)
goto out;
#endif
ptp_classifier_init();
out:
return err;
out_mount:
unregister_filesystem(&sock_fs_type);
goto out;
}