zoukankan      html  css  js  c++  java
  • 根文件系统之init


    title: 根文件系统之init
    tag: arm
    date: 2018-11-12 18:53:23

    引入

    在Kernel源码分析中,了解到init_post是在挂载根文件系统之后执行应用程序

    mark

    mark

    打开标准输入/输出/错误

    Linux首先打开标准输入scanf,标准输出printf,标准错误err

    
    if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
        printk(KERN_WARNING "Warning: unable to open an initial console.
    ");
    
    (void) sys_dup(0);	//这个是复制的意思
    (void) sys_dup(0);
    

    这里的sys_dup(0)表示复制打开的第0个文件,也就是/dev/console,也就是说准输入scanf,标准输出printf,标准错误err都定位到/dev/console这个文件,这个文件被称为终端,他可以是串口或者液晶键盘组合等

    执行init进程

    接下来会处理U-boot传递进来的命令行参数

    //run_init_process 一般会正确执行不会返回的程序
    if (execute_command) {
        run_init_process(execute_command);
        printk(KERN_WARNING "Failed to execute %s.  Attempting "
               "defaults...
    ", execute_command);
    }
    
    run_init_process("/sbin/init");
    run_init_process("/etc/init");
    run_init_process("/bin/init");
    run_init_process("/bin/sh");
    
    panic("No init found.  Try passing init= option to kernel.");
    

    我们搜索下execute_command,发现如下定义,很明显和kernel源码分析中的命令行参数类似

    static int __init init_setup(char *str)
    {
    	unsigned int i;
    
    	execute_command = str;
    	/*
    	 * In case LILO is going to boot us with default command line,
    	 * it prepends "auto" before the whole cmdline which makes
    	 * the shell think it should execute a script with such name.
    	 * So we ignore all arguments entered _before_ init=... [MJ]
    	 */
    	for (i = 1; i < MAX_INIT_ARGS; i++)
    		argv_init[i] = NULL;
    	return 1;
    }
    __setup("init=", init_setup);
    
    

    也是设置一个段属性固定的结构体

    #define __setup(str, fn)					
    	__setup_param(str, fn, fn, 0)
    
    #define __setup_param(str, unique_id, fn, early)			
    	static char __setup_str_##unique_id[] __initdata = str;	
    	static struct obs_kernel_param __setup_##unique_id	
    		__attribute_used__				
    		__attribute__((__section__(".init.setup")))	
    		__attribute__((aligned((sizeof(long)))))	
    		= { __setup_str_##unique_id, fn, early }
    
    

    也就是构造了一个和root=/dev/mtdblock3类似的

    static char __setup_str_init_dev_setup[] __initdata = "init=";
    static struct obs_kernel_param __setup_init_dev_setup 
        __attribute_used__
        __attribute__((__section__(".init.setup")))	
    	__attribute__((aligned((sizeof(long)))))	
        ={
        	__setup_str_init_dev_setup,root_init_setup,init_dev_setup,0
     	}
     	
    这个结构体的原型如下
    struct obs_kernel_param 
    {
    	const char *str;
    	int (*setup_func)(char *);
    	int early;
    };
    

    也就是说execute_command=/linuxrc,因为u-boot传递的参数是init=/linuxrc,程序会使用run_init_process(execute_command);来处理这个命令行

    注意 函数run_init_process一般会正确执行不会返回的程序,也就是说如果能够正确执行u-boot传递的参数,将不会执行以下

    run_init_process("/sbin/init");	//如果命令行参数不正确才会执行这个应用程序
    run_init_process("/etc/init");
    run_init_process("/bin/init");
    run_init_process("/bin/sh");
    
    panic("No init found.  Try passing init= option to kernel.");
    

    小结测试

    (一)

    烧录u-boot,烧录Linux,擦除根文件系统nand erase root,也就是不放根文件系统,系统会有如下提示

    VFS: Mounted root (yaffs filesystem).       
    挂接了根文件系统,但是flash是空的,默认识别为yaffs
    Freeing init memory: 140K
    Warning: unable to open an initial console.
    flash是空的,无法启动应用程序
    Failed to execute /linuxrc.  Attempting defaults...
    错误指示--命令行
    Kernel panic - not syncing: No init found.  Try passing init= option to kernel.
    

    因为格式化了flash,系统可以识别为任意的文件系统,默认识别为yaffs,但是由于没有根文件系统,所以无法打开标准输入输出,按照代码所写的提示错误

    printk(KERN_WARNING "Warning: unable to open an initial console.
    ");
    

    同时也就无法打开init进程,提示

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

    (二)

    烧入根文件系统,在u-boot下输入y,下载文件系统 fs_mini.yaffs2,然后启动.输入ps看下启动的应用程序

    # ps
      PID  Uid        VSZ Stat Command
        1 0          3092 S   init
        2 0               SW< [kthreadd]
        3 0               SWN [ksoftirqd/0]
        4 0               SW< [watchdog/0]
        5 0               SW< [events/0]
        6 0               SW< [khelper]
       55 0               SW< [kblockd/0]
       56 0               SW< [ksuspend_usbd]
       59 0               SW< [khubd]
       61 0               SW< [kseriod]
       73 0               SW  [pdflush]
       74 0               SW  [pdflush]
       75 0               SW< [kswapd0]
       76 0               SW< [aio/0]
      710 0               SW< [mtdblockd]
      745 0               SW< [kmmcd]
      767 0          3096 S   -sh
      769 0          3096 R   ps
    

    这里init就是启动的第一个进程sh也就是终端接收输入以及打印的输出

    init实现

    在嵌入式Linux中的一些基础命令例如ls,cp等实际上也是一个个App,这些基本命令一般由busybox编译得到一个名为busybox的应用程序.然后ls,cd,cp等命令一般是其链接.可以使用ls-l xxx来查看其链接属性.可以先用which xxx查看其位置,然后看属性

    # ls -l /bin/ls
    lrwxrwxrwx    1 1000     1000            7 Jan  6  2010 /bin/ls -> busybox
    
    # ls
    bin         lib         mnt         sbin        usr
    dev         linuxrc     proc        sys
    etc         lost+found  root        tmp
    
    # busybox ls
    bin         lib         mnt         sbin        usr
    dev         linuxrc     proc        sys
    etc         lost+found  root        tmp
    

    其实,/sbin/init也是到busybox的链接

    run_init_process("/sbin/init");
    run_init_process("/etc/init");
    run_init_process("/bin/init");
    run_init_process("/bin/sh");
    
    
    # which init
    /sbin/init
    # ls -l /sbin/init
    lrwxrwxrwx    1 1000     1000           14 Jan  6  2010 /sbin/init -> ../bin/busybox
    
    
  • 相关阅读:
    POJ2524+并查集
    POJ3697+BFS+hash存边
    POJ1151+线段树+扫描线
    POJ2528+线段树
    ubuntu 和 win7 远程登陆 + vnc登陆
    POJ3690+位运算
    POJ3283+字典树
    POJ3282+模拟
    POJ2349+prim
    2016.6.13
  • 原文地址:https://www.cnblogs.com/zongzi10010/p/10023703.html
Copyright © 2011-2022 走看看