Linux内核网络源码分析——建立套接字
目录:Linux内核网络源码分析
socket()
user
————————————————–
kernel
sys_socketcall() <net/socket.c>
asmlinkage long sys_socketcall(int call, unsigned long __user *args)
…
case SYS_SOCKET:
err = sys_socket(a0, a1, a[2]);
break;
…
sys_socket() <net/socket.c>
asmlinkage long sys_socket(int family, int type, int protocol)
…
retval = sock_create(family, type, protocol, &sock);
…
retval = sock_map_fd(sock);
//为套接字分配一个文件描述符并分配一个file文件,
//在应用层可象处理文件一样处理套接字了。
…
sock_create() <net/socket.c>
int sock_create(int family, int type, int protocol, struct socket **res)
{
return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
// current宏用于获取当前进程的task_struct
}
__sock_create()
static int __sock_create(struct net *net, int family, int type, int protocol,
struct socket **res, int kern)
…
pf = rcu_dereference(net_families[family]);//获取net_proto_family结构
…
err = pf->create(net, sock, protocol);
// 使用net_proto_family的create函数构建BSD Socket
// 当family为AF_INET时,调用的是inet_create
…
inet_create() <net/ipv4/af_inet.c> //Create an inet socket
static int inet_create(struct net *net, struct socket *sock, int protocol)
…
sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot);
// 根据指定协议为sock分配内存空间,并初始化
…
if (sk->sk_prot->init) {
err = sk->sk_prot->init(sk);//调用协议(struct proto)指定的初始化函数
…
// 如果类型是SOCK_STREAM的话会调用tcp_v4_init_sock,
// 而SOCK_DGRAM类型的socket没有额外的初始化了,到此socket调用结束
// 参见:
inet_init() <net/ipv4/af_inet.c:>
static struct inet_protosw inetsw_array[] <net/ipv4/af_inet.c:>
struct proto tcp_prot={…} <net/ipv4/tcp_ipv4.c>
struct proto udp_prot={…} <net/ipv4/udp.c>
socket()
user
————————————————–
kernel
sys_socketcall() <net/socket.c>
asmlinkage long sys_socketcall(int call, unsigned long __user *args)
…
case SYS_SOCKET:
err = sys_socket(a0, a1, a[2]);
break;
…
sys_socket() <net/socket.c>
asmlinkage long sys_socket(int family, int type, int protocol)
…
retval = sock_create(family, type, protocol, &sock);
…
retval = sock_map_fd(sock);
//为套接字分配一个文件描述符并分配一个file文件,
//在应用层可象处理文件一样处理套接字了。
…
sock_create() <net/socket.c>
int sock_create(int family, int type, int protocol, struct socket **res)
{
return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
// current宏用于获取当前进程的task_struct
}
__sock_create()
static int __sock_create(struct net *net, int family, int type, int protocol,
struct socket **res, int kern)
…
pf = rcu_dereference(net_families[family]);//获取net_proto_family结构
…
err = pf->create(net, sock, protocol);
// 使用net_proto_family的create函数构建BSD Socket
// 当family为AF_INET时,调用的是inet_create
…
inet_create() <net/ipv4/af_inet.c> //Create an inet socket
static int inet_create(struct net *net, struct socket *sock, int protocol)
…
sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot);
// 根据指定协议为sock分配内存空间,并初始化
…
if (sk->sk_prot->init) {
err = sk->sk_prot->init(sk);//调用协议(struct proto)指定的初始化函数
…
// 如果类型是SOCK_STREAM的话会调用tcp_v4_init_sock,
// 而SOCK_DGRAM类型的socket没有额外的初始化了,到此socket调用结束
// 参见:
inet_init() <net/ipv4/af_inet.c:>
static struct inet_protosw inetsw_array[] <net/ipv4/af_inet.c:>
struct proto tcp_prot={…} <net/ipv4/tcp_ipv4.c>
struct proto udp_prot={…} <net/ipv4/udp.c>
This entry was posted in Software Development. Bookmark the permalink.
No comments:
Post a Comment