根文件系统之init(一)



title: 根文件系统之init(一)

tag: arm

date: 2018-11-12 18:53:23

---

引入

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

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

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.\n");

(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...\n", 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.\n");

同时也就无法打开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

原文地址:https://www.cnblogs.com/zongzi10010/p/9955472.html

时间: 2024-10-27 20:28:09

根文件系统之init(一)的相关文章

根文件系统之init

title: 根文件系统之init tag: arm date: 2018-11-12 18:53:23 --- 引入 在Kernel源码分析中,了解到init_post是在挂载根文件系统之后执行应用程序 打开标准输入/输出/错误 Linux首先打开标准输入scanf,标准输出printf,标准错误err if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) printk(KERN_WARNING &

构建根文件系统之init进程分析

busybox是ls.cp等命令的集合. 执行ls时,实际上是执行了busybox ls 执行cp时,实际上是执行了busybox cp 分析init程序之前,再让我们回想一下我们的目标:u-boot启动内核,内核启动应用程序,内核是怎样启动应用程序呢,内核启动了init进程,位于/sbin/init中.我们最终的目的是启动客户程序,也就是说假如你是做手机的,希望启动一个手机的程序,假如是做监控的,那么就启动一个监控的程序的.客户各有不同,但都使用了linux系统,那么怎样加以区分呢? init

第4阶段——制作根文件系统之编译配置安装busybox(3)

在上一节分析出制作一个最小的根文件系统至少需要: (1)/dev/console(终端控制台, 提供标准输入.标准输出以及标准错误) /dev/null  (为空的话就是/dev/null, 所有写到这个文件中的数据都会被丢弃掉.) (2)init进程的程序(也就是busybox,因为init程序位于busybox中) (3)/etc/inittab(用于init进程读取配置, 然后执行inittab里的指定应用程序) (4)应用程序(被inittab配置文件调用的应用程序) (5)C库(gli

根文件系统袁丽丽

1.1.根文件系统概述 1.为什么需要根文件系统 (1)init进程的应用程序在根文件系统上 (2)根文件系统提供了根目录/ (3)内核启动后的应用层配置(etc目录)在根文件系统上 (4)shell命令程序在根文件系统上 总结:一套Linux体系,只有内核本身是不能工作,必须要根文件系统相配合,主要是要根文件系统/etc下的配置文件./bin./sbin等目录下的shell命令相配合等等,还有/lib下的库文件(静态链接库,动态链接库)等等 1.2.根文件系统的实质 (1).根文件系统是特殊用

Qemu搭建ARM vexpress开发环境(三)----NFS网络根文件系统

Qemu搭建ARM vexpress开发环境(三)----NFS网络根文件系统 标签(空格分隔): Qemu ARM Linux 经过上一篇<Qemu搭建ARM vexpress开发环境(二)----通过u-boot启动Linux内核>,已经实现了通过u-boot加载Kernel启动开发板,并且挂载根文件系统,本文讲述通过NFS网络挂载根文件系统. 通过NFS网络根文件系统,可以实现开发板在通过u-boot启动内核后,通过NFS网络在别的PC主机上挂载根文件系统.对于开发调试阶段的工作学习提供

Busybox构建根文件系统和制作Ramdisk

定制根文件系统的方法很多,最常用的是使用BusyBox来构建定制根文件系统.它集成压缩了Linux的许多工具和命令,可以使用户迅速方便地建立一套相对完整.功能丰富的文件系统,其中包括大量常用的应用程序.下面详细介绍有关Busybox定制根文件系统. 一.系统环境: 1.操作系统:Ubuntu140.4 2.交叉编译工具:gcc version 6.1.1 20160711 (Linaro GCC 6.1-2016.08) 3.busybox源码包:busybox-1.26.2 二.构建rootf

2017.3.2学习笔记----------nfs以及根文件系统

根文件系统的制作烧写,nfs,驱动程序的编译 <1> 根文件系统的制作烧写: 类似于前一节,步骤可以参考手册,将补丁文件打入虚拟机,再安装即可. 具体步骤参考开发板应用手册3.4节 <2> 使用flash上的根文件系统启动沪,手工MOUNT NFS: mount -t nfs -o nolock,vers=2 192.168.1.132:/work/nfs_root /mnt ls  /mnt <3>使用nfs作为根文件系统来启动 进入uboot: set bootar

根文件系统挂载过程

目录 注册挂载rootfs文件系统 解压initramfs到rootfs中 prepare_namespace挂载磁盘上的文件系统 注册挂载rootfs文件系统 首先是rootfs的注册和挂载,rootfs作为一切后续文件操作的基石. start_kernel vfs_caches_init mnt_init init_rootfs注册rootfs文件系统 init_mount_tree 挂载rootfs文件系统 vfs_kern_mount mount_fs type->mount其实是roo

Linux之根文件系统的构建20160611

说一下LINUX根文件系统的构建: 制作文件系统 1. 交叉编译busybox 安装:make install CONFIG_PREFIX=/work/nfs_root/fs_mini_mdev_new 2. 安装库 mkdir /work/nfs_root/fs_mini_mdev_new/lib mkdir /work/nfs_root/fs_mini_mdev_new/usr/lib -p cp /usr/local/arm/4.3.2/arm-none-linux-gnueabi/lib