异想天开

What's the true meaning of light, Could you tell me why

线程

日期:2015-02-08 23:17:34
  
最后更新日期:2015-02-08 23:23:28
【技术笔记】
操作系统概念的线程分为1v1线程和Nv1线程,对应我们工程概念就是内核线程和协程(用户态线程)。Nv1线程即指多个用户态线程对应一个内核态线程。这里分析的步骤是这样的,用c写测试程序,strace查看系统调用,同时查看内核源码的索引,解释原理。这里以2.6.30版本为例。通过strace命令发现,不论是fork还是pthread_create,最终转化的系统调用都是clone。如下: [code lang="cpp"]
//fork调用转化后的clone调用
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb75ec728) =2496
//pthread_create调用转化后的clone调用
clone(child_stack=0xb759a464, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb759aba8, {entry_number:6, base_addr:0xb759ab40, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}, child_tidptr=0xb759aba8) = 2518
[/code]
而clone调用之前并不熟悉,查阅得知:
[code lang="cpp"]
long sys_clone(unsigned long clone_flags, unsigned long newsp,
void __user *parent_tid, void __user *child_tid)
{
long ret;

if (!newsp)
newsp = UPT_SP(&current->thread.regs.regs);
current->thread.forking = 1;
ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
child_tid);
current->thread.forking = 0;
return ret;
}
[/code]
从而说明不论创建进程和线程,都是使用了do_fork调用。线程的其他问题在此忽略了。下面提一个问题?内存描述符mm_struct结构为啥有两个表示计数的成员mm_count和mm_users?内核线程,共享了进程的内存描述符mm_struct,意思是进程每创建一个线程,增加了进程mm_struct的mm_users引用计数。mm_count是进程级别的引用计数,fork一次初始化为1。在do_fork里面找mm_struct相关的函数调用,如下调用链:
[code lang="cpp"]
do_fork -> copy_process -> copy_mm
[/code]
线程的clone_flags有CLONE_VM位。
[code lang="cpp"]
static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) {
...
oldmm = current->mm;
if (clone_flags & CLONE_VM) {
atomic_inc(&oldmm->mm_users);
mm = oldmm;
goto good_mm;
}
...
}
[/code]
继续查看进程相关的:
[code lang="cpp"]
static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
{
atomic_set(&mm->mm_users, 1);
atomic_set(&mm->mm_count, 1);
...
}
[/code]
调用序列为:
[code lang="cpp"]
static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
struct mm_struct *dup_mm(struct task_struct *tsk)
static int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
//后面就是相同的过程了 copy_process <- do_fork
[/code]
完毕
参考:
1.内核源码引用列表