CentOS6 切换启动时的图形/文本界面的分析

虚拟机分配的内存较小,需要关闭图形界面。通过分析发现,kernel启动时,执行kernel_init()函数(init/main.c):先新建一个initrd(init Ram Disk,内存中的文件系统,挂载到/),然后执行init_post()。

 1 static int __init kernel_init(void * unused)
 2 {
 3     lock_kernel();
 4 
 5     /*
 6      * init can allocate pages on any node
 7      */
 8     set_mems_allowed(node_possible_map);
 9     /*
10      * init can run on any cpu.
11      */
12     set_cpus_allowed_ptr(current, cpu_all_mask);
13     /*
14      * Tell the world that we're going to be the grim
15      * reaper of innocent orphaned children.
16      *
17      * We don't want people to have to make incorrect
18      * assumptions about where in the task array this
19      * can be found.
20      */
21     init_pid_ns.child_reaper = current;
22 
23     cad_pid = task_pid(current);
24 
25     smp_prepare_cpus(setup_max_cpus);
26 
27     do_pre_smp_initcalls();
28     start_boot_trace();
29 
30     smp_init();
31     sched_init_smp();
32 
33     do_basic_setup();
34 
35     /*
36      * check if there is an early userspace init.  If yes, let it do all
37      * the work
38      */
39 
40     if (!ramdisk_execute_command)
41         ramdisk_execute_command = "/init";
42 
43     if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
44         ramdisk_execute_command = NULL;
45         prepare_namespace();
46     }
47 
48     /*
49      * Ok, we have completed the initial bootup, and
50      * we're essentially up and running. Get rid of the
51      * initmem segments and start the user-mode stuff..
52      */
53 
54     init_post();
55     return 0;
56 }

 

而在init_post()中,试图从多个位置查找init可执行文件,最后运行shell兜底(37~40行):

 1 static noinline int init_post(void)
 2     __releases(kernel_lock)
 3 {
 4     /* need to finish all async __init code before freeing the memory */
 5     async_synchronize_full();
 6     free_initmem();
 7     unlock_kernel();
 8     mark_rodata_ro();
 9     system_state = SYSTEM_RUNNING;
10     numa_default_policy();
11 
12     if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
13         printk(KERN_WARNING "Warning: unable to open an initial console.\n");
14 
15     (void) sys_dup(0);
16     (void) sys_dup(0);
17 
18     current->signal->flags |= SIGNAL_UNKILLABLE;
19 
20     if (ramdisk_execute_command) {
21         run_init_process(ramdisk_execute_command);
22         printk(KERN_WARNING "Failed to execute %s\n",
23                 ramdisk_execute_command);
24     }
25 
26     /*
27      * We try each of these until one succeeds.
28      *
29      * The Bourne shell can be used instead of init if we are
30      * trying to recover a really broken machine.
31      */
32     if (execute_command) {
33         run_init_process(execute_command);
34         printk(KERN_WARNING "Failed to execute %s.  Attempting "
35                     "defaults...\n", execute_command);
36     }
37     run_init_process("/sbin/init");
38     run_init_process("/etc/init");
39     run_init_process("/bin/init");
40     run_init_process("/bin/sh");
41 
42     panic("No init found.  Try passing init= option to kernel.");
43 }

在CentOS6中,/sbin/init属于upstart这个包,它是ubuntu对传统System V  init daemon的一项重大改进,CentOS直接拿来主义了。它最大的优点:支持事件和热插拔。参考这里:http://upstart.ubuntu.com/cookbook/

/sbin/init
|__/etc/init/*.conf 或*.override 系统级
|__/etc/dbus-1/system.d/Upstart.conf 用户级

而/etc/init/rc.conf、/etc/init/rcS.conf是/sbin/init执行的2个普通任务,

  •  /etc/init/rc.conf

              |__ /etc/rc.d/rc
                     它遍历:/etc/rc$runlevel.d/K*后执行initctl starting JOB=....  来启动各种服务

  •  /etc/init/rcS.conf

              |__ /etc/rc.d/rc.sysinit
                       |__ /etc/inittab: 【这里获取要进入的runlevel,id:5:initdefault:,5表示GUI界面】
                       |__ exec telinit $runlevel  【注意这里是重点,直接设置当前runlevel】

  • chkconfig 改变的是/etc/rcXX.d 链接

【注】CentOS7 用 /lib/systemd/system/default.target来取代/etc/inittab。

所以,只需要修改/etc/inittab: id:3:initdefault: 即可每次重启到控制台界面。

posted @ 2018-01-15 15:35  zcan  阅读(960)  评论(0编辑  收藏  举报