免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2853 | 回复: 5
打印 上一主题 下一主题

[进程管理] 请教个idle进程的问题。 [复制链接]

求职 : 系统工程师等
论坛徽章:
5
技术图书徽章
日期:2014-04-19 22:01:05天蝎座
日期:2014-05-09 13:49:28双子座
日期:2014-06-16 15:08:042015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:55:28
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-04-09 15:41 |只看该作者 |倒序浏览
从网上查了下idle进程和init进程的分析:
init_task是静态制造出来的,pid=0,它试图将从最早的汇编代码一直到start_kernel的执行都纳入到init_task进程上下文中。
请问这句话怎么理解呢?

个人理解:
init_task只是静态的定义了下:
struct task_struct init_task = INIT_TASK(init_task);
EXPORT_SYMBOL(init_task);

最终的执行:
rest_init函数里会调用:

        /* Call into cpu_idle with preempt disabled */
        cpu_idle();

而cpu_idle函数:
void cpu_idle(void)
{
        int cpu = smp_processor_id();

        current_thread_info()->status |= TS_POLLING;

        /* endless idle loop with no priority at all */
        while (1) {
                tick_nohz_stop_sched_tick(1);
                while (!need_resched()) {

                        check_pgt_cache();
                        rmb();

                        if (rcu_pending(cpu))
                                rcu_check_callbacks(cpu, 0);

                        if (cpu_is_offline(cpu))
                                play_dead();

                        local_irq_disable();
                        __get_cpu_var(irq_stat).idle_timestamp = jiffies;
                        /* Don't trace irqs off for idle */
                        stop_critical_timings();
                        pm_idle();
                        start_critical_timings();
                }
                tick_nohz_restart_sched_tick();
                preempt_enable_no_resched();
                schedule();
                preempt_disable();
        }
}

cpu_idle里,执行一个死循环,这里开始执行idle(init_task)了!


ps:linux内核版本号为2.3.27。


不知我的理解是否正确?另外,前面的那句话(试图将从最早的汇编代码一直到start_kernel的执行都纳入到init_task进程上下文中)又如何理解呢?

谢谢!

欢迎各位大侠各抒己见,讨论下!

论坛徽章:
0
2 [报告]
发表于 2013-04-13 16:11 |只看该作者
本帖最后由 junnyg 于 2013-04-13 16:13 编辑

回复 1# qxhgd

个人理解:
start_kernel的最后一步会执行rest_init函数

  1. asmlinkage void __init start_kernel(void)
  2. {
  3.         ... ...
  4.         /* Do the rest non-__init'ed, we're now alive */
  5.         rest_init();
  6. }
复制代码
在rest_init函数中会启动一个内核线程执行kernel_init函数,这个内核线程将成为我们所说的init进程
  1. static noinline void __init_refok rest_init(void)
  2.         __releases(kernel_lock)
  3. {
  4.         ... ...
  5.         kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
  6.         ... ...

  7.         /* Call into cpu_idle with preempt disabled */
  8.         cpu_idle();
  9. }
复制代码
kernel_init执行initrd的加载,并最终调用initrd中的指向的init程序(默认/init,或者启动参数中加“init=/xxx"指定)

  1. static int __init kernel_init(void * unused)
  2. {
  3.         ......
  4.         /*
  5.          * check if there is an early userspace init.  If yes, let it do all
  6.          * the work
  7.          */

  8.         if (!ramdisk_execute_command)
  9.                 ramdisk_execute_command = "/init";

  10.         if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
  11.                 ramdisk_execute_command = NULL;
  12.                 prepare_namespace();
  13.         }

  14.         /*
  15.          * Ok, we have completed the initial bootup, and
  16.          * we're essentially up and running. Get rid of the
  17.          * initmem segments and start the user-mode stuff..
  18.          */

  19.         init_post();
  20.         return 0;
  21. }
  22. /* This is a non __init function. Force it to be noinline otherwise gcc
  23. * makes it inline to init() and it becomes part of init.text section
  24. */
  25. static noinline int init_post(void)
  26.         __releases(kernel_lock)
  27. {
  28.         /* need to finish all async __init code before freeing the memory */
  29.         async_synchronize_full();
  30.         free_initmem();
  31.         unlock_kernel();
  32.         mark_rodata_ro();
  33.         system_state = SYSTEM_RUNNING;
  34.         numa_default_policy();


  35.         current->signal->flags |= SIGNAL_UNKILLABLE;

  36.         if (ramdisk_execute_command) {
  37.                 run_init_process(ramdisk_execute_command);
  38.                 printk(KERN_WARNING "Failed to execute %s\n",
  39.                                 ramdisk_execute_command);
  40.         }

  41.         /*
  42.          * We try each of these until one succeeds.
  43.          *
  44.          * The Bourne shell can be used instead of init if we are
  45.          * trying to recover a really broken machine.
  46.          */
  47.         if (execute_command) {
  48.                 run_init_process(execute_command);
  49.                 printk(KERN_WARNING "Failed to execute %s.  Attempting "
  50.                                         "defaults...\n", execute_command);
  51.         }
  52.         run_init_process("/sbin/init");
  53.         run_init_process("/etc/init");
  54.         run_init_process("/bin/init");
  55.         run_init_process("/bin/sh");

  56.         panic("No init found.  Try passing init= option to kernel. "
  57.               "See Linux Documentation/init.txt for guidance.");
  58. }
复制代码
而start_kernle函数的最终流程是调用cpu_idle()函数进入死循环,成为系统中的idle进程
   

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
3 [报告]
发表于 2013-04-13 17:16 |只看该作者
回复 1# qxhgd
在多处理系统中,每个CPU多有一个进程0。只要打开机器电源,计算机的BIOS就启动某一个cpu,同时禁用其他CPU。运行在CPU0上的swapper进程初始化内核数据结构,然后激活其他CPU,并通过copy_process()函数创建另外的swapper进程,把0传给新创建的swapper进程作为它们新的PID。此外,内核把适当的CPU索引复制给内核所创建的每个进程的thread_info描述符的CPU字段。
CPU的idle进程的创建:

start_kernel-->rest_init-->kernel_init-->smp_init-->cpu_up-->_cpu_up-->__cpu_up-->smp_ops.cpu_up-->native_cpu_up-->__smp_prepare_cpu-->do_warm_boot_cpu-->do_boot_cpu-->alloc_idle_task-->fork_idle-->copy_process

   

论坛徽章:
0
4 [报告]
发表于 2013-04-13 18:17 |只看该作者
回复 3# 瀚海书香
每个核都会有一个idle进程,但是init进程只有一个,是由主核启动的,不知道我理解的对吗?


   

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
5 [报告]
发表于 2013-04-15 08:41 |只看该作者
回复 4# junnyg
每个核都会有一个idle进程,但是init进程只有一个,是由主核启动的,不知道我理解的对吗?

可以这么理解。非主核的idle进程,就是init进程运行到最后复制出来的
   

求职 : 系统工程师等
论坛徽章:
5
技术图书徽章
日期:2014-04-19 22:01:05天蝎座
日期:2014-05-09 13:49:28双子座
日期:2014-06-16 15:08:042015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:55:28
6 [报告]
发表于 2013-04-16 11:15 |只看该作者
谢各位大侠,受教了!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP