卷二 Dalvik与Android源码分析 第二章 进程与线程 2.2 Dalvik线程创建机制 图书版试读--请勿转发
2014-03-13 15:15
756 查看
作者 crosskernel@gmail.com
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) );
}
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) );
}
相关文章推荐
- 卷二 Dalvik与Android源码分析 第二章 进程与线程 2.1 Dalvik虚拟机的进程创建机制 图书版试读--请勿转发
- 卷二 Dalvik与Android源码分析 第五章 Interpreter与JIT 5.6 dalvik运行时帧结构 图书版试读--请勿转发
- 卷二 Dalvik与Android源码分析 第五章 Interpreter与JIT 5.3-C解释器 5.4--汇编解释器 图书版试读--请勿转发
- 卷二 Dalvik与Android源码分析 第五章 Interpreter与JIT 5.5 Interpreter的切换 图书版试读--请勿转发
- 卷二 Dalvik与Android源码分析 第五章 Interpreter与JIT 5.1 解释器编译结构、5.2dalvik寄存器编译模型 图书版试读--请勿转发
- Android虚拟机学习总结Dalvik虚拟机进程和线程的创建过程分析
- Android虚拟机器学习总结Dalvik虚拟机创建进程和线程分析
- Android之Dalvik的进程/线程创建的过程
- Dalvik虚拟机进程和线程的创建过程分析
- Dalvik虚拟机进程和线程的创建过程分析
- Dalvik虚拟机进程和线程的创建过程分析
- [置顶] Android开发知识(四)Android进程间Binder通信机制的源码分析(下)
- Android事件转发机制—源码分析(一)
- Android进程/线程管理——深入源码解读+分析
- 【深入Java开发】JVM源码分析之一个Java进程究竟能创建多少线程
- 卷一 内核源代码分析 第二章 异常 2.2.4 OMAP4的中断体系 图书试读版-请勿转载
- Dalvik虚拟机进程和线程的创建过程分析
- Android线程间消息机制-Handler源码分析(FrameWork)
- Dalvik虚拟机进程和线程的创建过程分析
- Android2.2源码init机制分析