Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1150337
  • 博文数量: 241
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2279
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

JustForFun

文章分类

全部博文(241)

文章存档

2023年(8)

2022年(2)

2021年(3)

2020年(30)

2019年(11)

2018年(27)

2017年(54)

2016年(83)

2015年(23)

我的朋友

分类: LINUX

2016-09-22 19:24:47

init/main.c  kernel_init函数最后调用 init_post
在内核init线程的最后执行了init_post函数,在这个函数中真正启动了用户空间进程init
/* This is a non __init function. Force it to be noinline otherwise gcc
 * makes it inline to init() and it becomes part of init.text section
 */
main.c
static int noinline init_post(void)
{
    free_initmem();//释放所有init.* 段中的内存。
    unlock_kernel();
    mark_rodata_ro();//通过修改页表,保证只读数据段为只读属性。大部分构架为空函数。
    system_state = SYSTEM_RUNNING;//设置系统状态为运行状态
    numa_default_policy();//设定NUMA系统的内存访问策略为默认

        //打开控制台,这是标准输入
 //打开控制台,这样init进程就拥有一个控制台,并可以从中读取输入信息,也可以向其中写入信息 
    if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
        printk(KERN_WARNING "Warning: unable to open an initial console.\n");
//调用dup打开/dev/console文件描述符两次,这样控制太设备也可以供表述输出和标准错误使用(文件描述符为1和2)
    (void) sys_dup(0);        //出来文件描述符1          标准输出
    (void) sys_dup(0);    //出来文件描述符2 标出出错       文件描述符0,1,2都指向/dev/console


//sys_dup()的主要工作就是用来“复制”一个打开的文件号,使两个文件号都指向同一个文件
//不是“复制”吧,因该是申请一个新文件描述符,但是和原来的文件描述符指向同一个文件

//设置当前进程(init)为不可以杀进程(忽略致命的信号)
    current->signal->flags |= SIGNAL_UNKILLABLE;
//如果ramdisk_execute_command有指定的init程序,就执行它。
    if (ramdisk_execute_command) {
        run_init_process(ramdisk_execute_command);
        printk(KERN_WARNING "Failed to execute %s\n",
                ramdisk_execute_command);
    }

    /*
     * We try each of these until one succeeds.
     *
     * The Bourne shell can be used instead of init if we are
     * trying to recover a really broken machine.
     */
//如果execute_command有指定的init程序(uboot 传参数进去的init=),就执行它。
    if (execute_command) {
        run_init_process(execute_command);
        printk(KERN_WARNING "Failed to execute %s.  Attempting "
                    "defaults...\n", execute_command);
    }
  1. /****
  2. 在检查完ramdisk_execute_command和execute_command为空的情况下,顺序执行以下初始化程序:如果都没有找到就打印错误信息。这也是我们做系统移植的时候经常碰到的错误信息,出现这个信息很有可能是:
  3. 1、你的启动参数配置有问题,通过 指定了init程序,但是没有找到,且默认的那四个程序也不在文件系统中。
  4. 2、文件系统挂载有问题,文件不存在
  5. 3、init程序没有执行权限
  6. *******/


//sbin/init由busybox生成,所以可以到busybox里去查看细节,包括各个命令的源码都有。卫东山视频有这个的解释

// init/main.c    rest_init函数调用的kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
//kernel_init 调用init_post(); 调用run_init_process("/sbin/init");此时
kernel_init线程就变成"/sbin/init"线程了。
//可以用   #ps -elf查看以下
"/sbin/init"进程和[kthreadd]进程的父亲进程都是0号线程 
    run_init_process("/sbin/init");
    run_init_process("/etc/init");     //如果/sbin/init执行了。函数就再也不会返回。
    run_init_process("/bin/init");
    run_init_process("/bin/sh");

    panic("No init found.  Try passing init= option to kernel.");
}

装入并执行程序/sbin/init(变成一个用户进程).此后,init根据/etc/inittab配置文件来执行相应的脚本进行系统初始化,如设置键盘、字体,装载模块,设置网络等
init程序需要读取配置文件/etc/inittab。inittab是一个不可执行的文本文件,它有若干行指令所组成。




inittab文件内容如下:

# Default runlevel. The runlevels used are:
#   0 - halt (Do NOT set initdefault to this)
#   1 - Single user mode
#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
#   3 - Full multiuser mode
#   4 - unused
#   5 - X11
#   6 - reboot (Do NOT set initdefault to this)
id:5:initdefault:

###表示当前缺省运行级别为5(initdefault); 

###启动时自动执行/etc/rc.d/rc.sysinit脚本(sysinit)



inittab文件有以下格式:

  id:runlevel:action:process

1. id

  id是指入口标识符,它是一个字符串,对于getty或mingetty等其他login程序项,要求id与tty的编号相同,否则getty程序将不能正常工作。
2.

Runlevel 0 是让init关闭所有进程并终止系统。

  Runlevel 1是用来将系统转到单用户模式,单用户模式只能有系统管理员进入,在该模式下处理那些在有登录用户的情况下不能进行更改的文件,改runlevel的编号1也可以用S代替。

  Runlevel 2 是允许系统进入多用户的模式,但并不支持文件共享,这种模式很少应用。

  Runlevel 3 是最常用的运行模式,主要用来提供真正的多用户模式,也是多数服务器的缺省模式。

  Runlevel 4 一般不被系统使用,用户可以设计自己的系统状态并将其应用到runlevel4阶段,尽管很少使用,但使用该系统可以实现一些特定的登录请求。

  Runlevel 5 是将系统初始化为专用的XWindow终端。对功能强大的Linux系统来说,这并不是好的选择,但用户如果需要这样,也可以通过在runlevel启动来实现该方案。

  Runlevel 6 是关闭所有运行的进程并重新启动系统。
3. action

  action是描述其后的process的运行方式的。action可取的值包括:initdefault、sysinit、boot、bootwait等:
4. process

  process为具体的执行程序。程序后面可以带参数。

 

        由于init=/linuxrc,因此,在文件系统挂载后,运行的第一个程序就是根目录下的linuxrc,而这是一个指向/bin/busybox 的链接,也就是说,系统起来后运行的第一个程序就是busybox本身。                 

        busybox首先将试图解析/etc/inittab来获取进一步的初始化配置信息(参考busybox源代码init/init.c中的 parse_inittab()函数)。而事实上,root_qtopia中并没有/etc/inittab这个配置文件,根据busybox的裸机,它 将生成默认的配置。其中最重要的一个,就是new_init_action(SYSINIT,INIT_SCRIPT,""),也就决定了接下来初始化的 脚本是INIT_SCRIPT所定义的值,
这个宏的默认值是"etc/init.d/rcS"。
/etc/init.d/rcS是开机就会调用的脚本

#vi /etc/init.d/rcS

echo /sbin/mdev > /proc/sys/kernel/hotplug                                
/sbin/mdev -s                                                             
/bin/hotplug 


 
/etc/init.d/rcS文件系统启动时会调用
文件系统里存在/etc/mdev.conf文件,它包含了mdev的配置信息,mdev用来创建设备节点
由于启动时运行了命令:echo /sbin/mdev > /proc/sys/kernel/hotplug ,那么当有热插拔
事件产生时,内核就会调用位于/sbin 目录的mdev。这时mdev 通过环境变量中的 ACTION 和
DEVPATH,(这两个变量是系统自带的)来确定此次热插拔事件的动作以及影响了
/sys 中的那个目录。接着会看看这个目录中是否有“dev”的属性文件,如果有就利用这些信
息为这个设备在/dev 下创建设备节点文件。
[root@wangwenwen www]# cat  /sys/class/input/event0/uevent
MAJOR=13
MINOR=64
DEVNAME=input/event0
这个uevent就是为mdev提供信息的。

 

 










参考:http://blog.chinaunix.net/uid-20543672-id-3172321.html
参考:http://blog.csdn.net/ce123/article/details/8444482
http://blog.sina.com.cn/s/blog_67852f5601013t9e.html


阅读(2027) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~