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的強制轉換, 不大明白是什麼意思?
*/