android基于Socket的系统调用实现

本文详细介绍了在Android系统中,如何通过Socket实现系统调用的过程。从socket的定义到系统调用的软中断`swi`,再到中断向量表的设置和处理,以及最后如何通过`sys_call_table`调用相应的系统调用函数,如`sys_socket`。通过分析`kernel/net/Socket.c`中的`sock_create`和`sock_map_fd`等关键函数,揭示了创建和映射文件描述符的过程。

android基于Socket的系统调用实现


声明:该文件为本人原创,如转载修改及使用其中图片,请注明出处及原作者。

Author:lanbo(高兆成)

E-mail:lanbo_g@126.com

如有任何疑问可留言或E-mail

系统调用就是用户空间应用程序和内核提供的服务之间的接口。服务是由linux内核提供的,无法直接调用。因此必须使用一个进程来跨越用户空间和内核之间的界限。

今天我们就将从用户层通过socket来分析linux下的系统调用的实现过程。

通过该文章读者可熟悉系统调用的实现


 

以wpa_supplicant中driver_wext中的socket为例来分析:

要想通过wext与kernel沟通wpa_supplicant中是在wpa_driver_wext_init函数中通过创建socket来实现

Socket定义在bionic/libc/arch-arm/syscalls/socket.S中如下:

#include <sys/linux-syscalls.h>

 

   .text

    .type socket, #function

    .globl socket

   .align 4

   .fnstart

 

socket:

   .save   {r4, r7}

   stmfd   sp!, {r4, r7}

    ldr    r7, =__NR_socket//此处将__NR_socket放入到ARM R7中

    swi    #0//调用系统中断

   ldmfd   sp!, {r4, r7}

   movs    r0, r0

   bxpl    lr

   b       __set_syscall_errno

.fnend

 

__NR_socket 在几个文件中都有定义,我就不确认是调用的kernel/arch/arm/include/asm/Unistd.h还是

ndk/build/platforms/android-8/arch-arm/usr/include/sys/Linux-syscalls.h

#if !defined__ASM_ARM_UNISTD_H && !defined __ASM_I386_UNISTD_H

#if defined__arm__ && !defined __ARM_EABI__ && !defined __thumb__

  # define __NR_SYSCALL_BASE  0x900000

  #else

  # define  __NR_SYSCALL_BASE  0

  #endif

………………………省略号……………….

#define __NR_socket                       (__NR_SYSCALL_BASE +281)

 

如上调用了swi(软中断) ,接下来我们看看中断向量实现。

在ARM V4及V4T以后的大部分处理器中,中断向量表的位置可以有两个位置:一个是0,另一个是0xffff0000。可以通过CP15协处理器c1寄存器中V位(bit[13])控制。V和中断向量表的对应关系如下:

V=0:0x00000000~0x0000001C
        V=1:0xffff0000~0xffff001C

arch/arm/mm/proc-arm920.S中

.section".text.init", #alloc, #execinstr
        __arm920_setup:
        ……orr       r0, r0,#0x2100             @ ..1. ...1 ..11 ...1

//bit13=1 中断向量表基址为0xFFFF0000。R0的值将被付给CP15的C1.

 

中断向量在early_trap_init中定义,调用顺序如下:

start_kernel(kernel/init/main.c)==> setup_arch(kernel/arch/arm/kernel/Setup.c)==>early_trap_init(kernel/arch/arm/kernel/Traps.c)

 

early_trap_init部分代码如下:

unsigned longvectors = CONFIG_VECTORS_BASE;//定义中断向量起始地址

//#defineCONFIG_VECTORS_BASE 0xffff0000定义在kernel/include/linux/Autoconf.h

          extern char__stubs_start[], __stubs_end[];

          extern char__vectors_start[], __vectors_end[];

//如下做中断向量的搬移动作,为保护模式准备,如上调用swi后PC指针会指向vectors +address 0x00000008。

memcpy((void*)vectors, __vectors_start, __vectors_end -__vectors_start);

          memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);

          memcpy((void *)vectors + 0x1000 - kuser_sz,__kuser_helper_start, kuser_sz);

 

其中__stubs_start[], __stubs_end[],__vectors_start[], __vectors_end[]在kernel/arch/arm/kernel/dntry-armv.S中定义,我们来分析看看如何实现。

 

         .macro     vector_stub,name, mode, correction=0//此处定义了一个vector_stub宏定义

         .align        5

 

vector_\name:

         .if \correction

         sub   lr,lr, #\correction

         .endif

 

         @

         @ Save r0, lr_<exception> (parentPC) and spsr_<exception>

         @ (parent CPSR)

         @

         stmia        sp,{r0, lr}                   @ save r0, lr

         mrs  lr,spsr

         str    lr,[sp, #8]                   @ save spsr

 

         @

         @ Prepare for SVC32 mode.  IRQs remain disabled.

         @

         mrs  r0,cpsr

         eor   r0,r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)

         msr  spsr_

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值