构建linux根文件系统

2019-07-13 01:47发布

class="markdown_views prism-tomorrow-night">
  • 内核 启动后回去调用第一个程序init、给用户提供操作界面的shell程序 、应用程序所依赖的库文件。这些必须的基本的文件合起来称为根文件系统,他们存放在一个分区中,Linux系统启动之后首先挂载这个分区,称为挂载根文件系统,其他的分区上的所有的目录、文件的集合,也称之为文件系统。
  • linux系统中没有C、D、E等盘的概念,linux中以树状管理所有的文件目录,其他的分区挂载在这个目录上,这个目录被称之为挂载点或者安装点,然后可以通过这个分区来访问这个分区上的文件了,比如根文件系统被挂载在根目录’/‘上之后,就可以在’/'看到根目录下的文件了
  • 在一个分区上存储文件时需要遵循一定的格式,这种格式称之为文件系统,比如fat16、ntfs、wxt2、ext3、jffs2、yaffs2等,除了这几个拥有实实在在的存储分区的文件系统之外,linux还有几个虚拟的文件系统类型,比如proc、yaffs等,他们的文件并不存在实际的设备上,而是访问他们时有linux内核临时的生成。
  • /etc下的文件
    export 用来配置NFS文件系统
    fstab 用来指明执行"mount -a"时的需要挂载的文件系统
    mtab 用来显示已经加载的文件系统,通常是/proc/mounts的链接文件
    ftpusers 启动FTP服务时,用来配置用户的访问权限
    group 用户的组文件
    inittab init进程的配置文件
    ld.so.conf 其它共享库的路径
    passed 密码文件
  • /proc目录
    proc可以为空,linux内核创建的临时文件,proc文件系统,是一个虚拟的文件系统,他没有实际的存储设备,里面的目录、文件都是内核临时生成的,用来表示系统的运行状态,也可已操作其中的文件控制系统。
    系统启动之后使用以下命令挂载proc文件系统(常在/etc/fstab进行设置以自动挂载)
#mount -t proc none /proc
  • /tmp用于存放临时文件,减少系统对flash的操作,所以/tmp目录必须保证可以访问到。可使用以下命令记性==进行挂载
# mount -t tmpfs none /tmp

linux文件类型

  • 普通文件
  • 目录文件
  • 字符设备文件
  • 块设备文件
  • FIFO
  • 套接字
  • 连接文件

启动第一个程序init

文件在linux源码的init/main.c中 /* 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 */ //若果使用的是 __attribute__(noinline)的话代表的是,返回的出错将被当成警告处理 static int noinline init_post(void) { free_initmem(); unlock_kernel(); mark_rodata_ro(); system_state = SYSTEM_RUNNING; numa_default_policy(); 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); //因为是linux内核刚刚启动所以打开的文件描述符是0、1、2,并且使用sys_dup将0、1、2都连接到打开的额console上 //> 之后就能实现将标准输入标准输出和标注错误输出重定向到console上。 if (ramdisk_execute_command) { run_init_process(ramdisk_execute_command); printk(KERN_WARNING "Failed to execute %s ", 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 = /linuxrc //因为这种函数都是死循环的样式进行的,所以无论是 /linuxrc还是 // /sbin/init 等程序都是只能执行一个 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."); } busybox的init程序对应代码中的init/init.c文件
执行的过程如下:
在这里插入图片描述

busybox的inittab配置文件

在这里插入图片描述
上图中的-/bin/sh中的 '-'代表程序是交互的方式启动,这时就会弹出交互式shell窗口,嵌入式设备中是使用串口
在这里插入图片描述
下面是我的开发板上的inittab配置文件 # /etc/inittab init(8) configuration for BusyBox # # Copyright (C) 1999-2004 by Erik Andersen # # # Note, BusyBox init doesn't support runlevels. The runlevels field is # completely ignored by BusyBox init. If you want runlevels, use sysvinit. # # # Format for each entry: ::: # # : WARNING: This field has a non-traditional meaning for BusyBox init! # # The id field is used by BusyBox init to specify the controlling tty for # the specified process to run on. The contents of this field are # appended to "/dev/" and used as-is. There is no need for this field to # be unique, although if it isn't you may have strange results. If this # field is left blank, it is completely ignored. Also note that if # BusyBox detects that a serial console is in use, then all entries # containing non-empty id fields will be ignored. BusyBox init does # nothing with utmp. We don't need no stinkin' utmp. # # : The runlevels field is completely ignored. # # : Valid actions include: sysinit, respawn, askfirst, wait, once, # restart, ctrlaltdel, and shutdown. # # Note: askfirst acts just like respawn, but before running the specified # process it displays the line "Please press Enter to activate this # console." and then waits for the user to press enter before starting # the specified process. # # Note: unrecognised actions (like initdefault) will cause init to emit # an error message, and then go along with its business. # # : Specifies the process to be executed and it's command line. # # Note: BusyBox init works just fine without an inittab. If no inittab is # found, it has the following default behavior: # ::sysinit:/etc/init.d/rcS # ::askfirst:/bin/sh # ::ctrlaltdel:/sbin/reboot # ::shutdown:/sbin/swapoff -a # ::shutdown:/bin/umount -a -r # ::restart:/sbin/init # # if it detects that /dev/console is _not_ a serial console, it will # also run: # tty2::askfirst:/bin/sh # tty3::askfirst:/bin/sh # tty4::askfirst:/bin/sh # # Boot-time system configuration/initialization script. # This is run first except when booting in single-user mode. # ::sysinit:/etc/init.d/rcS # /bin/sh invocations on selected ttys # # Note below that we prefix the shell commands with a "-" to indicate to the # shell that it is supposed to be a login shell. Normally this is handled by # login, but since we are bypassing login in this case, BusyBox lets you do # this yourself... # # Start an "askfirst" shell on the console (whatever that may be) ::askfirst:-/bin/sh # Start an "askfirst" shell on /dev/tty2-4 new_init_action(ASKFIRST, bb_default_login_shell, ""); new_init_action(ASKFIRST, bb_default_login_shell, VC_2); new_init_action(ASKFIRST, bb_default_login_shell, VC_3); new_init_action(ASKFIRST, bb_default_login_shell, VC_4); VC_2 ==> tty2 ASKFIRST ==> askfirst -/bin/sh ==> bb_default_login_shell tty2::askfirst:-/bin/sh tty3::askfirst:-/bin/sh tty4::askfirst:-/bin/sh # /sbin/getty invocations for selected ttys tty4::respawn:/sbin/getty 38400 tty5 tty5::respawn:/sbin/getty 38400 tty6 # Example of how to put a getty on a serial line (for a terminal) #::respawn:/sbin/getty -L ttyS0 9600 vt100 #::respawn:/sbin/getty -L ttyS1 9600 vt100 # # Example how to put a getty on a modem line. #::respawn:/sbin/getty 57600 ttyS2 # Stuff to do when restarting the init process ::restart:/sbin/init # Stuff to do before rebooting ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r ::shutdown:/sbin/swapoff -a 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述