现在的位置: 首页 > 综合 > 正文

uclinux第一个用户程序的加载

2013年09月19日 ⁄ 综合 ⁄ 共 2076字 ⁄ 字号 评论关闭

快乐虾

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)

 

 

抱歉!评论已关闭.