内核线程是怎么运行

pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)  通过这个函数可以创建内核线程,运行一个指定函数fn。
但是这个fn是怎么运行的了?

pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
	struct pt_regs regs;

	memset(®s, 0, sizeof(regs));

	regs.ARM_r4 = (unsigned long)arg;
	regs.ARM_r5 = (unsigned long)fn;   //做标记
	regs.ARM_r6 = (unsigned long)kernel_thread_exit;
	regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;
	regs.ARM_pc = (unsigned long)kernel_thread_helper;   //这个很重要会将fn正确运行
	regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;

	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);
}


接着do_fork->copy_process(clone_flags, stack_start, regs, stack_size, child_tidptr, NULL, trace);->copy_thread(clone_flags, stack_start, stack_size, p, regs);

int
copy_thread(unsigned long clone_flags, unsigned long stack_start,
	    unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs)
{
	struct thread_info *thread = task_thread_info(p);
	struct pt_regs *childregs = task_pt_regs(p);  //获得线程的内核栈

	*childregs = *regs;//将之前kernel_thread的内容复制过来,如fn,kernel_thread_helper,这一步很重要,因为建立了子线程的堆栈环境,以后这个线程被schedule后,会将这里面保存的寄存器恢复,会运行kernel_thread_helper  。regs.ARM_pc = (unsigned long)kernel_thread_helper;



	childregs->ARM_r0 = 0;
	childregs->ARM_sp = stack_start;

	memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
	thread->cpu_context.sp = (unsigned long)childregs;
	thread->cpu_context.pc = (unsigned long)ret_from_fork;

	clear_ptrace_hw_breakpoint(p);

	if (clone_flags & CLONE_SETTLS)
		thread->tp_value = regs->ARM_r3;

	thread_notify(THREAD_NOTIFY_COPY, thread);

	return 0;
}


而kernel_thread_helper定义为找到,但注释已经说的很清楚了,如下:

/*
 * Shuffle the argument into the correct register before calling the
 * thread function.  r4 is the thread argument, r5 is the pointer to
 * the thread function, and r6 points to the exit function.
 */
extern void kernel_thread_helper(void);
asm(	".pushsection .text\n"
"	.align\n"
"	.type	kernel_thread_helper, #function\n"
"kernel_thread_helper:\n"
#ifdef CONFIG_TRACE_IRQFLAGS
"	bl	trace_hardirqs_on\n"
#endif
"	msr	cpsr_c, r7\n"
"	mov	r0, r4\n"
"	mov	lr, r6\n"
"	mov	pc, r5\n"  //将fn赋值给pc,终于原形毕露了
"	.size	kernel_thread_helper, . - kernel_thread_helper\n"
"	.popsection");


先弄到这,当然还有很多进程切换的细节未提到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值