linux kernel start process

首先执行前面的一下汇编代码, C语言的入口是在init/main.c 的 start_kernel 函数,在这个函数中进行时钟,内存,中断等的初始化,然后执行rest_init()函数,其中再执行cpu_idle()函数, 在这会有一个while循环

/* endless idle loop with no priority at all */
        while (1) {
                idle_notifier_call_chain(IDLE_START);
                tick_nohz_idle_enter();
                rcu_idle_enter();
                while (!need_resched()) {
#ifdef CONFIG_HOTPLUG_CPU
                        if (cpu_is_offline(smp_processor_id()))
                                cpu_die();
#endif

                        /*
                         * We need to disable interrupts here
                         * to ensure we don't miss a wakeup call.
                         */
                        local_irq_disable();
#ifdef CONFIG_PL310_ERRATA_769419
                        wmb();
#endif
                        if (hlt_counter) {
                                local_irq_enable();
                                cpu_relax();
                        } else if (!need_resched()) {
                                stop_critical_timings();
                                if (cpuidle_idle_call())
                                        pm_idle();
                                start_critical_timings();
                                /*
                                 * pm_idle functions must always
                                 * return with IRQs enabled.
                                 */
                                WARN_ON(irqs_disabled());
                        } else
                                local_irq_enable();
                }
                rcu_idle_exit();
                tick_nohz_idle_exit();
                idle_notifier_call_chain(IDLE_END);
                schedule_preempt_disabled();
        }

该循环会不断轮询进程的pcb链表,执行获得cpu控制权的进程.

进程的pcb实际上时struct task_struct的结构体.

系统调用实际的流程如下
1.保存函数的参数到寄存器
2.保存系统调用号到eax
3.执行0x80中断
4.系统调用执行完后,返回值保存在eax中
以下是执行time系统调用的汇编代码

int TimeAsm(int argc, char *argv[])
{
    time_t tt;
    struct tm *t;
    asm volatile(
        "mov $0,%%ebx\n\t"
        "mov $0xd,%%eax\n\t" 
        "int $0x80\n\t" 
        "mov %%eax,%0\n\t"  
        : "=m" (tt) 
    );
    t = localtime(&tt);
    printf("time:%d:%d:%d:%d:%d:%d\n",t->tm_year+1900, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
    return 0;
}

cpu一般情况下在执行cpu_idle中的循环,当系统调用发生后,产生中断,执行中断处理也就是执行系统调用,结束后再继续cpu_idle的循环.

创建进程的解析
APP中执行fork,最后内核中会调用sys_clone函数,sys_clone最后会调用do_fork函数.
那么fork为什么能返回两个返回值呢?子进程返回0,父进程返回值大于0.原因是在do_fork中会复制父进程的pcb,然后修改其中的返回值使得两份pcb有不同的返回值.而cpu_idle的轮询是根据pcb进行的,多了一个pcb也就相当于多了一个进程,并且多出来的pcb保存的返回值与原来的不一样,这样在执行完系统调用fork后就表现为fork具有两个返回值.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值