im coming home歌词:Android socket创建、绑定流程分析(一)

来源:百度文库 编辑:偶看新闻 时间:2024/05/04 11:26:58
Android socket创建、绑定流程分析(一)2011年08月01日 星期一 22:10

首先要了解一下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;

       }

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

}