您的位置:首页 > 移动开发 > Android开发

卷二 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) );

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐