`
xiaoer_1982
  • 浏览: 1815950 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

uclinux第一个用户程序的加载

阅读更多

快乐虾

http://blog.csdn.net/lights_joy/

lights@hb165.com

本文适用于

ADSP-BF561

uclinux-2008r1.5-RC3(smp patch)

Visual DSP++ 5.0(update 5)

欢迎转载,但请保留作者信息

系统中的第一个用户线程应该是/bin/init。内核使用了

run_init_process("/bin/init");

创建用户线程。这个函数的实现为:

static void run_init_process(char *init_filename)

{

argv_init[0] = init_filename;

kernel_execve(init_filename, argv_init, envp_init);

}

即它将调用kernel_execve函数创建用户线程。kernel_execve的实现在文件arch\blackfin\mach-common\entry.S中:

ENTRY(_kernel_execve)

link SIZEOF_PTREGS;

p0 = sp;

r3 = SIZEOF_PTREGS / 4;

r4 = 0(x);

.Lclear_regs:

[p0++] = r4;

r3 += -1;

cc = r3 == 0;

if !cc jump .Lclear_regs (bp);

p0 = sp;

sp += -16;

[sp + 12] = p0;

call _do_execve;

SP += 16;

cc = r0 == 0;

if ! cc jump .Lexecve_failed;

/* Success. Copy our temporary pt_regs to the top of the kernel

* stack and do a normal exception return.

*/

r1 = sp;

r0 = (-KERNEL_STACK_SIZE) (x);

r1 = r1 & r0;

p2 = r1;

p3 = [p2];

r0 = KERNEL_STACK_SIZE - 4 (z);

p1 = r0;

p1 = p1 + p2;

p0 = fp;

r4 = [p0--];

r3 = SIZEOF_PTREGS / 4;

.Lcopy_regs:

r4 = [p0--];

[p1--] = r4;

r3 += -1;

cc = r3 == 0;

if ! cc jump .Lcopy_regs (bp);

r0 = (KERNEL_STACK_SIZE - SIZEOF_PTREGS) (z);

p1 = r0;

p1 = p1 + p2;

sp = p1;

r0 = syscfg;

[SP + PT_SYSCFG] = r0;

[p3 + (TASK_THREAD + THREAD_KSP)] = sp;

RESTORE_CONTEXT;

rti;

.Lexecve_failed:

unlink;

rts;

ENDPROC(_kernel_execve)

这个函数首先在当前内核线程的栈上留了一个struct pt_regs的空间并将它们全部置0,接着调用do_execve。内核调用kernel_execve时传递了三个参数进来,分别保存在R0, R1, R2三个寄存器中,但是do_execve有四个参数

int do_execve(char * filename,

char __user *__user *argv,

char __user *__user *envp,

struct pt_regs * regs)

因此还要将regs的指针传递进去,由于这是第四个参数,需要通过栈来传递。在执行完do_execve函数后,regs中将保存用户程序开始执行时所必须的各个寄存器的值,其PC指针将指向用户程序在SDRAM中的第一行可执行程序,而SP将指向动态创建的thread_info

在此之后,执行RESTORE_CONTEXT,这个宏将把RETI寄存器的值设置为struct pt_regs结构体中的pc成员的值,因此在最后执行rti指令的时候就将跳转到用户程序开始执行。

在内核中调用用户程序时,通常处于时钟中断或者中断15的状态,因此最后一条rti指令将使DSP退出super mode,从而进入user mode运行。

1 参考资料

uclinux第一个内核线程的运行(2009-4-23)

uclinux内核线程的创建(2009-4-23)

fork_inituclinux内核的线程数量限制(2009-4-22)

uclinux内核的任务优先级及其load_weight(2009-4-22)

init_thread_union猜想(2009-1-17)

uclinux2.6(bf561)内核中的current_thread_info(2008/5/12)

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics