grep -irn "int socket" path_4_linux_src
或者 souceinsight 类似的工具查看
看了部分,发现bind ---> sys_bind 搜索如下
*
* AUTHOR: anhk
* DATE: 2007-5-23
*
* 这是学习网络部分的笔记, 比较粗糙, 并且把一些引用计数代码去掉了.
* 还有部分加锁的代码
* sys_socketcall[net/socket.c]函数是整个网络的中断入口函数
*/
asmlinkage long sys_socketcall(int call, unsigned long __user *args);
{
unsigned long a[6];
/* 从用户空间得到信息,该函数是SMP安全的 */
if (copy_from_user(a, args, nargs[call]))
return -EFAULT;
switch (call) {
case SYS_SOCKET:
err = sys_socket(a[0], a[1], a[2]);
break;
case SYS_BIND:
err = sys_bind(a[0], (struct sockaddr __user *)a[1], a[2]);
break;
case SYS_CONNECT:
err = sys_connect(a[0], (struct sockaddr __user *)a[1], a[2]);
break;
....
}
}
/*
* 然后跟进到sys_socket[net/socket.c]函数, 该函数调用sock_create函数,
* sock_create函数调用__sock_create函数,
* __sock_create函数, 生成一个inode, 加入到inode_in_use队列中, 并把其中的inode的用户id和
* 组id设成当前进程的用户id及组id
*
* sock_map_fd函数新建一个struct file *newfile结构, 加入到当前进程的current->files
* 然后查找当前进程的一个可用的fd描述符,并与该newfile结构进行绑定
* sock->file = newfile
*/
asmlinkage long sys_socket(int family, int type, int protocol)
{
int retval;
struct socket *sock;
retval = sock_create(family, type, protocol, &sock);
if (retval < 0)
goto out;
retval = sock_map_fd(sock);
if (retval < 0)
goto out_release;
out:
/* It may be already another descriptor 8) Not kernel problem. */
return retval;
out_release:
sock_release(sock);
return retval;
}
int sock_create(int family, int type, int protocol, struct socket **res)
{
return __sock_create(family, type, protocol, res, 0);
}
/*
* 下边看__sock_create函数, 调用sock_alloc()
* sock_alloc负责生成new_inode()
* inode->i_mode = S_IFSOCK | S_IRWXUGO;
* inode->i_uid = current->fsuid;
* inode->i_gid = current->fsgid;
* list_add(&inode->i_list, &inode_in_use);
* 然后绑定sock及这个inode
* sock = SOCKET_I(inode);
* 然后根据family在net_families[family]中找到create函数, 在tcp/udp/raw中该函数都是inet_create()
*/
static int __sock_create(int family, int type, int protocol,
struct socket **res, int kern)
{
int err;
struct socket *sock;
const struct net_proto_family *pf;
/* 检查type, family是否越界 */
....;
/* 生成inode并初始化 */
sock = sock_alloc();
if (!sock) {
if (net_ratelimit())
printk(KERN_WARNING "socket: no more sockets/n");
return -ENFILE; /* Not exactly a match, but its the
closest posix thing */
}
sock->type = type;
/*
* 定义:
* struct net_proto_family {
* int family;
* int (*create)(struct socket *sock, int protocol);
* struct module *owner;
* };
*
* static const struct net_proto_family *net_families[NPROTO] __read_mostly;
* 该结构在 int sock_register(const struct net_proto_family *ops)中被初始化
net_families[ops->family] = ops;
* 如果在tcp/ip协议中,该sock_register在net/ipv4/af_inet.c:inet_init(void)调用
*/
/* 得到net_families中相应family的数据结构 */
/* 这里 pf->create = inet_create[net/ipv4/af_inet.c] */
pf = rcu_dereference(net_families[family]);
/*
* 不管TCP/UDP/RAW, 这里的pf->create 在[net/ipv4/af_inet.c]中被初始化为inet_create[net/ipv4/af_inet.c]
*/
err = pf->create(sock, protocol);
if (err < 0)
goto out_module_put;
*res = sock;
return 0;
}
/*
* 该函数设置sock->state = SS_UNCONNECTED;
*
* 这里有一个结构[net/ipv4/af_inet.c]
* static struct inet_protosw inetsw_array[] =
* {
* {
* .type = SOCK_STREAM,
* .protocol = IPPROTO_TCP,
* .prot = &tcp_prot,
* .ops = &inet_stream_ops,
* .capability = -1,
* .no_check = 0,
* .flags = INET_PROTOSW_PERMANENT |
* INET_PROTOSW_ICSK,
* },
*
* {
* .type = SOCK_DGRAM,
* .protocol = IPPROTO_UDP,
* .prot = &udp_prot,
* .ops = &inet_dgram_ops,
* .capability = -1,
* .no_check = UDP_CSUM_DEFAULT,
* .flags = INET_PROTOSW_PERMANENT,
* },
*
*
* {
* .type = SOCK_RAW,
* .protocol = IPPROTO_IP,
* .prot = &raw_prot,
* .ops = &inet_sockraw_ops,
* .capability = CAP_NET_RAW,
* .no_check = UDP_CSUM_DEFAULT,
* .flags = INET_PROTOSW_REUSE,
* }
* };
*
* 根据sock->type找到相应的结构地址, 如
* tcp: answer = &inetsw_array[0];
* udp: answer = &inetsw_array[1];
* answer_prot = answer->prot;
*
* 然后申请一个struct sock *sk结构,
* 如果是TCP, 该结构加入hash表tcp_hashinfo中, 然后调用 tcp_v4_init_sock[net/ipv4/tcp_ipv4.c],
* 如果是UDP, 没有类似的hash表,且pf->prot->init = NULL
* udp_prot->hash = udp_lib_hash[include/net/udp.h]
*
* static inline void udp_lib_hash(struct sock *sk)
* {
* BUG();
* }
* 可以说udp_prot->hash什么都没做, 我想知道如果udp协议,这个struct sock *sk放到哪里去了?
*/
static int inet_create(struct socket *sock, int protocol)
{
struct sock *sk;
struct list_head *p;
struct inet_protosw *answer;
struct inet_sock *inet;
struct proto *answer_prot;
unsigned char answer_flags;
char answer_no_check;
int try_loading_module = 0;
int err;
sock->state = SS_UNCONNECTED;
/* Look for the requested type/protocol pair. */
answer = NULL;
lookup_protocol:
err = -ESOCKTNOSUPPORT;
rcu_read_lock();
/*
* static struct list_head inetsw[SOCK_MAX];
*/
/*
* 根据inetsw找到inetsw_array中的相应协议, 并用answer指向该地址
* 即:
* TCP: answer = &inetsw_array[0]
* UDP: answer = &inetsw_array[1]
* answer_prot = answer->prot, tcp为tcp_prot, udp为udp_prot;
*/
list_for_each_rcu(p, &inetsw[sock->type]) {
answer = list_entry(p, struct inet_protosw, list);
/* Check the non-wild match. */
if (protocol == answer->protocol) {
if (protocol != IPPROTO_IP)
break;
} else {
/* Check for the two wild cases. */
if (IPPROTO_IP == protocol) {
protocol = answer->protocol;
break;
}
if (IPPROTO_IP == answer->protocol)
break;
}
err = -EPROTONOSUPPORT;
answer = NULL;
}
if (unlikely(answer == NULL)) {
/* 加载模块 */
...;
}
err = -EPERM;
if (answer->capability > 0 && !capable(answer->capability))
goto out_rcu_unlock;
/*
* TCP:answer->ops = inetsw_array[0].ops = &inet_stream_ops,
* UDP:answer->ops = inetsw_array[1].ops = &inet_dgram_ops,
*/
sock->ops = answer->ops;
/*
* TCP:answer->prot = inetsw_array[0].prot = &tcp_prot
* UDP:answer->prot = inetsw_array[1].prot = &udp_prot
*/
answer_prot = answer->prot;
answer_no_check = answer->no_check;
answer_flags = answer->flags;
rcu_read_unlock();
BUG_TRAP(answer_prot->slab != NULL);
err = -ENOBUFS;
/*
* 在sk_alloc函数中初始化sk
* sk = kmalloc(answer_prot->obj_size, 1);
* sk->sk_prot = sk->sk_prot_creator = answer_prot = inetsw_array[].prot;
*/
sk = sk_alloc(PF_INET, GFP_KERNEL, answer_prot, 1);
if (sk == NULL)
goto out;
err = 0;
sk->sk_no_check = answer_no_check;
if (INET_PROTOSW_REUSE & answer_flags)
sk->sk_reuse = 1;
/* 强制转换, 不知道什么意思 ^_^ */
inet = inet_sk(sk);
inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
if (SOCK_RAW == sock->type) {
inet->num = protocol;
if (IPPROTO_RAW == protocol)
inet->hdrincl = 1;
}
if (ipv4_config.no_pmtu_disc)
inet->pmtudisc = IP_PMTUDISC_DONT;
else
inet->pmtudisc = IP_PMTUDISC_WANT;
inet->id = 0;
/*
* sk->sk_socket = sock;
* sock->sk = sk;
*/
sock_init_data(sock, sk);
sk->sk_destruct = inet_sock_destruct;
sk->sk_family = PF_INET;
sk->sk_protocol = protocol;
sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
inet->uc_ttl = -1;
inet->mc_loop = 1;
inet->mc_ttl = 1;
inet->mc_index = 0;
inet->mc_list = NULL;
sk_refcnt_debug_inc(sk);
if (inet->num) {
inet->sport = htons(inet->num);
/*
* tcp: sk 放到tcp_hashinfo, udp呢?
*
* tcp_prot->hash = &tcp_v4_hash[net/ipv4/tcp_ipv4.c]
*/
sk->sk_prot->hash(sk);
}
/* udp_prot->init = NULL,所以这里只有tcp,raw */
if (sk->sk_prot->init) {
/*
* tcp_prot.init = tcp_v4_init_sock,
* raw_prot.init = raw_init
*/
err = sk->sk_prot->init(sk);
if (err)
sk_common_release(sk);
}
out:
return err;
out_rcu_unlock:
rcu_read_unlock();
goto out;
}
/*
* 一共申请了 4 个结构
* struct inode -> 放到 inode_in_use 链表中
* struct socket *sock: sock->file = newfile
* 被sock_map_fd处理, 最后放到newfile->ops
* struct file *newfile -> 放到 current->files中
* struct sock *sk: tcp: tcp_hashinfo.ehash[]
* udp: sk放到哪里了?
* 还有 一些对struct socket *sock或struct sock *sk的强制转换, 不大明白是什么意思?
*/
Linux中socket的构造过程
最新推荐文章于 2024-03-13 01:01:13 发布