卷二 Dalvik与Android源码分析 第二章 进程与线程 2.2 Dalvik线程创建机制 图书版试读--请勿转发

作者 [email protected]


Bionic的线程机制是Dalvik线程的机制的基础。其实现是通过Linux的Fork机制来实现的。线程的运行轨迹是栈,

Android代码注释里已经给出了的bionic线程的栈结构:


* +---------------------------+
 * |     pthread_internal_t    |
 * +---------------------------+
 * |                           |
 * |          TLS area         |
 * |                           |
 * +---------------------------+
 * |                           |
 * .                           .
 * .         stack area        .
 * .                           .
 * |                           |
 * +---------------------------+
 * |         guard page        |
 * +---------------------------+
 
由此可见,线程栈结构是最低层存放该线程的管理结构pthread_internal_t;接着是线程局部存储区域;再接着是运行时产生的堆栈数据。


/* 线程的创建实现遵循pthread API。实现如下:*/
int pthread_create(pthread_t *thread_out, pthread_attr_t const * attr,
                   void *(*start_routine)(void *), void * arg)
{
     …


    //若未准备堆栈,则分配堆栈,栈是线程的人生轨迹


    if (!attr->stack_base) {
        stack = mkstack(stackSize, attr->guard_size);
        …
    } else {
        stack = attr->stack_base;
    }


    //预留线程局部存储
    tls = (void**)(stack + stackSize - BIONIC_TLS_SLOTS*sizeof(void*));
   …
   //调用__pthread_clone,见下文
    tid = __pthread_clone((int(*)(void*))start_routine, tls,
                CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND
                | CLONE_THREAD | CLONE_SYSVSEM | CLONE_DETACHED,
                arg);


   …
}




//r1是堆栈地址
ENTRY(__pthread_clone)
    .cantunwind

    /*把新线程入口地址填入堆栈,在新线程从内核退出时会从这里找到其实执行地址。*/
str     r0, [r1, #-4]
//系统调用需要的参数信息
    str     r3, [r1, #-8]


   // CLONE_VM等信息放在r0,遵循内核调用规范
    mov     r0, r2


    @ new sp is already in r1


#if __ARM_EABI__
//保存下来r4-r7
stmfd   sp!, {r4, r7}
//系统调用clone
    ldr     r7, =__NR_clone
    swi     #0
#else
    swi     #__NR_clone
#endif
    //新线程的r0为“0”,参见内核部分
    movs    r0, r0
    …
blt     __error
//创建线程冲这里返回
bxne    lr
//新线程继续执行
//取出存放在新线程堆栈里起始地址和参数
    ldr     r0, [sp, #-4]
ldr     r1, [sp, #-8]
//新线程的堆栈指针指向TLS区域,参见上文堆栈结构
    mov     r2, sp @ __thread_entry needs the TLS pointer
sub     lr, lr
//新线程继续调用“__thread_entry”
    b       __thread_entry

END(__pthread_clone)


//新线程的trampoline
void __thread_entry(int (*func)(void*), void *arg, void **tls)
{
    int retValue;
    pthread_internal_t * thrInfo;
    …
    thrInfo = (pthread_internal_t *) tls[TLS_SLOT_THREAD_ID];
   //初始化新线程的线程局部存储
    __init_tls( tls, thrInfo );
    //跳转到新线程的起始地址
    pthread_exit( (void*)func(arg) );
}

你可能感兴趣的:(thread,android,虚拟机,dalvik)