im coming home歌词:Android socket创建、绑定流程分析(一)
来源:百度文库 编辑:偶看新闻 时间:2024/05/04 11:26:58
首先要了解一下Linux的系统调用:
系统调用就是用户空间应用程序和内核提供的服务之间的接口。服务是由linux内核提供的,无法直接调用。因此必须使用一个进程来跨越用户空间和内核之间的界限。这让我想起了android进程间通讯机制IBinder就是做这么个事情的。当然也有其他方式跨越用户空间与内核的,比如通过软中断来实现。
以dhcp创建socket为例:
从上面可以看出socket通过swi产生了软中断,r7保存中断号(eabi的一个规范)。Unistd.h中定义了各个中断号。(参考android-2.0\bionic\libc\arch-arm\syscalls\socket.s)内核代码版本2.6.28.6。
#define __NR_socket (__NR_SYSCALL_BASE+281)
__NR_socket中断号对应的处理函数为:
Sys_socket
这可以从arch\arm\kernel\call.s中找到:
/* 280 */ CALL(sys_waitid)
CALL(sys_socket)
CALL(ABI(sys_bind, sys_oabi_bind))
CALL(ABI(sys_connect, sys_oabi_connect))
CALL(sys_listen)
Sys_socket在中断表中的位置与定义的中断号一致,这样当产生软中断时,直接通过中断号查找system_call_table就能关联相应的处理函数。(参考vector_swi软中断入口)
system_call_table生成可以参考arch\arm\kernel\entry-common.s中代码:
。。。。。。。。。。
#define CALL(x) .long x
。。。。。。。。。
.type sys_call_table, #object
ENTRY(sys_call_table)
#include "calls.S"
#undef ABI
#undef OBSOLETE
Sys_socket实现可以参考(net\socket.c):
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)。
将宏SYSCALL_DEFINE3展开即可得到。
Socket创建与bind操作
了解了linux system call后再来看socket的创建就比较简单了,从上面可知,应用程序调用socket后最终通过软中断call sys_socket。Sys_socket 在net/socket.c中定义:
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
retval = sock_create(family, type, protocol, &sock);
if (retval < 0)
goto out;
retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
if (retval < 0)
goto out_release;
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}
int sock_create(int family, int type, int protocol, struct socket **res)
{
return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
}
static int __sock_create(struct net *net, int family, int type, int protocol,
struct socket **res, int kern)
{
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
err = security_socket_create(family, type, protocol, kern); //检查应用是否有权限创建socket等
if (err)
return err;
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
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;
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
rcu_read_lock();
pf = rcu_dereference(net_families[family]); //获取net protocal family以PF_PACKET为例
err = -EAFNOSUPPORT; //packet_init调用sock_register(&packet_family_ops);
if (!pf) //注册PF_PACKET socket协议类别。
goto out_release;
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
err = pf->create(net, sock, protocol); //调用packet_creat函数af_packet.c
if (err < 0)
goto out_module_put;
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}
static int packet_create(struct net *net, struct socket *sock, int protocol)
{
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
err = -ENOBUFS;
sk = sk_alloc(net, PF_PACKET, GFP_KERNEL, &packet_proto);
if (sk == NULL)
goto out;
sock->ops = &packet_ops; //比如SOCK_DGRAM
if (sock->type == SOCK_PACKET)
sock->ops = &packet_ops_spkt;
sock_init_data(sock, sk);
po = pkt_sk(sk);
sk->sk_family = PF_PACKET;
po->num = proto; //网络协议比如TCP_IP:0x8000 ARP:0x0806
sk->sk_destruct = packet_sock_destruct;
sk_refcnt_debug_inc(sk);
/*
* Attach a protocol block
*/
spin_lock_init(&po->bind_lock);
mutex_init(&po->pg_vec_lock);
po->prot_hook.func = packet_rcv; //添加接收处理函数,当底层通过neif_rx通知上层有数据时,最终会
//会调用此function
if (sock->type == SOCK_PACKET)
po->prot_hook.func = packet_rcv_spkt;
po->prot_hook.af_packet_priv = sk;
if (proto) {
po->prot_hook.type = proto;
dev_add_pack(&po->prot_hook); //dev_add_pack 看一下这个函数的说明就知道,他的作用
sock_hold(sk); //在网络协议栈中增加协议的处理函数。
po->running = 1;
}
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
}