基于itop4412开发板 busybox制作的最小文件系统分析

《基于itop4412开发板 busybox制作的最小文件系统分析》


--------------------------------------------------------
参考《朱老师物联网大讲堂》uboot和系统移植-第16部分

很大部分参考朱老师的课件,最过分的是还有直接复制粘贴的,一方面实在是不会表达,另一方面是真的不会,引用一下,见怪莫怪。可能会有错误,希望指正。
在此也为朱有鹏老师打个广告,有兴趣可以去了解一下《朱老师物联网大讲堂》
--------------------------------------------------------
一、根文件系统引入
1.根文件系统概述
 1.1、为什么需要根文件系统
 (1)init进程的应用程序在根文件系统上
 (2)根文件系统提供了根目录/
 (3)内核启动后的应用层配置(etc目录)在根文件系统上。几乎可以认为:发行版=内核+rootfs
 (4)shell命令程序在根文件系统上。譬如ls、cd等命令
 总结:一套linux体系,只有内核本身是不能工作的,必须要rootfs(上的etc目录下的配置文件、/bin  /sbin等目录下的shell命令,还有/lib目录下的库文件等···)
 相配合才能工作。


 1.2、根文件系统的实质是什么
 (1)根文件系统是特殊用途的文件系统。
 (2)根文件系统也必须属于某种文件系统格式。rootfstype=
 (3)究竟文件系统是用来干嘛的。ZnFAT
 首先,存储设备(块设备,像硬盘、flash等)是分块(扇区)的,物理上底层去访问存储设备时是按照块号(扇区号)来访问的。这就很麻烦。
 其次,文件系统是一些代码,是一套软件,这套软件的功能就是对存储设备的扇区进行管理,将这些扇区的访问变成了对目录和文件名的访问。
 我们在上层按照特定的目录和文件名去访问一个文件时,文件系统会将这个目录+文件名转换成对扇区号的访问。
 最后,不同的文件系统的差异就在于对这些扇区的管理策略和方法不同,譬如坏块管理、碎片管理。


2.根文件系统的形式
 2.1、镜像文件形式
 (1)使用专用工具软件制作的可供烧录的镜像文件
 (2)镜像中包含了根文件系统中的所有文件
 (3)烧录此镜像类似于对相应分区格式化。
 (4)镜像文件系统具有一定的格式,格式是内化的,跟文件名后缀是无关的。
 
 2.2、文件夹形式
 (1)根文件系统其实就是一个包含特定内容的文件夹而已
 (2)根文件系统可由任何一个空文件夹添加必要文件构成而成
 (3)根文件系统的雏形就是在开发主机中构造的文件夹形式的
 
 2.3、总结
 (1)镜像文件形式的根文件系统主要目的是用来烧录到块设备上,设备上的内核启动后去挂载它。镜像文件形式的根文件系统是由文件夹形式的根文件系统使用专用的镜像制作工具
  制作而成的。
 (2)最初在开发主机中随便mkdir创建了一个空文件夹,然后向其中添加一些必要的文件(包括etc目录下的运行时配置文件、/bin等目录下的可执行程序、/lib目录下的库文件等···)
  后就形成了一个文件夹形式的rootfs。然后这个文件夹形式的rootfs可以被kernel通过nfs方式来远程挂载使用,但是不能用来烧录块设备。我们为了将这个rootfs烧录到块设备中
  于是用一些专用的软件工具将其制作成可供烧录的一定格式的根文件系统镜像。
 (3)文件夹形式的rootfs是没有格式的,制作成镜像后就有了一定的rootfs格式了,格式是由我们的镜像制作过程和制作工具来决定的。每一种格式的镜像制作工具的用法都不同。
 
3.自己制作ext2格式的根文件系统
 3.1、mke2fs介绍
 (1)mke2fs是一个应用程序,在ubuntu中默认是安装了的。这个应用程序就是用来制作ext2、ext3、ext4等格式的根文件系统的。
 (2)一般用来制作各种不同格式的rootfs的应用程序的名字都很相似,类似于mkfs.xxx(譬如用来制作ext2格式的rootfs的工具叫mkfs.ext2、用来制作jffs2格式的rootfs的工具
  就叫mkfs.jffs2)
 (3)ubuntu14.04中的mkfs.ext2等都是mke2fs的符号链接而已。


 3.2、动手制作ext2格式的根文件系统
 (1)创建rootfs.ext2文件并且将之挂载到一个目录下方便访问它
《参考资料:http://blog.csdn.net/zhengmeifu/article/details/24174513》
  dd if=/dev/zero of=rootfs.ext2 bs=1024 count=2048
  losetup  /dev/loop1 rootfs.ext2
  mke2fs -m 0 /dev/loop1 2048
  mount -t ext2 /dev/loop1 ./rootfs/
 (2)我们向镜像中写入一个普通文件linuxrc。这个文件就会成为我们制作的镜像中的/linuxrc。内核挂载了这个镜像后就会尝试去执行/linuxrc。然后执行时必然会失败。我们将来实验看到的现象就应该是:挂载成功,执行/linuxrc失败。
 (3)将来真正去做有用的rootfs时,就要在这一步添加真正可以执行的linuxrc程序,然后还要添加别的/lib目录下的库文件,/etc目录下的配置文件等。
 (4)卸载掉,然后镜像就做好了。
  umount /dev/loop1
  losetup -d /dev/loop1


3.3、烧录制作的rootfs.ext2
 (1)以上制作出来的根文件系统只是一个空壳,只能挂在,并不能有什么实际作用。
 (2)挂载时注意bootargs传参设置。
 (3)可以看打印信息,看挂载是否成功,关键看"VFS:"后面的信息。


4.nfs方式启动自制简易文件夹形式的rootfs
 4.1、什么是nfs
 (1)nfs是一种网络通讯协议,由服务器和客户端构成。
 (2)nfs的作用。利用nfs协议可以做出很多直接性应用,我们这里使用nfs主要是做rootfs挂载。开发板中运行kernel做nfs客户端,主机ubuntu中搭建nfs服务器。
  在主机ubuntu的nfs服务器中导出我们制作的文件夹形式的rootfs目录,则在客户端中就可以去挂载这个文件夹形式的rootfs进而去启动系统。
 (3)搭建nfs服务器。
 
 4.2、配置内核以支持nfs作为rootfs
 (1)设置nfs启动方式的bootargs
 (2)在menuconfig中配置支持nfs启动方式 
 4.3、总结
 (1)nfs方式启动相当于开发板上的内核远程挂载到主机上的rootfs
 (2)nfs方式启动不用制作rootfs镜像
 (3)nfs方式不适合真正的产品,一般作为产品开发阶段调试使用




5.到底什么是linuxrc
 5.1、/linuxrc是一个可执行的应用程序
 (1)/linuxrc是应用层的,和内核源码一点关系都没有
 (2)/linuxrc在开发板当前内核系统下是可执行的。因此在ARM SoC的linux系统下,这个应用程序就是用arm-linux-gcc编译链接的;如果是在PC机linux系统下,
  那么这个程序就是用gcc编译连接的。
 (3)/linuxrc如果是静态编译连接的那么直接可以运行;如果是动态编译连接的那么我们还必须给他提供必要的库文件才能运行。但是因为我们/linuxrc这个程序是
 由内核直接调用执行的,因此用户没有机会去导出库文件的路径,因此实际上这个/linuxrc没法动态连接,一般都是静态连接的。


 5.2、/linuxrc执行时引出用户界面
 (1)操作系统启动后在一系列的自己运行配置之后,最终会给用户一个操作界面(也许是cmdline,也许是GUI),这个用户操作界面就是由/linuxrc带出来的。
 (2)用户界面等很多事并不是在/linuxrc程序中负责的,用户界面有自己专门的应用程序,但是用户界面的应用程序是直接或者间接的被/linuxrc调用执行的。
  用户界面程序和其他的应用程序就是进程2、3、4·····,这就是我们说的进程1(init进程,也就是/linuxrc)是其他所有应用程序进程的祖宗进程。


 5.3、/linuxrc负责系统启动后的配置
 (1)就好像一个房子建好之后不能直接住,还要装修一样;操作系统启动起来后也不能直接用,要配置下。
 (2)操作系统启动后的应用层的配置(一般叫运行时配置,英文简写etc)是为了让我们的操作系统用起来更方便,更适合我个人的爱好或者实用性。


 5.4、/linuxrc在嵌入式linux中一般就是busybox
 (1)busybox是一个C语言写出来的项目,里面包含了很多.c文件和.h文件。这个项目可以被配置编译成各个平台下面可以运行的应用程序。
  我们如果用arm-linux-gcc来编译busybox就会得到一个可以在我们开发板linux内核上运行的应用程序。
 (2)busybox这个程序开发出来就是为了在嵌入式环境下构建rootfs使用的,也就是说他就是专门开发的init进程应用程序。
 (3)busybox为当前系统提供了一整套的shell命令程序集。譬如vi、cd、mkdir、ls等。在桌面版的linux发行版(譬如ubuntu、redhat、centOS等)中
  vi、cd、ls等都是一个一个的单独的应用程序。但是在嵌入式linux中,为了省事我们把vi、cd等所有常用的shell命令集合到一起构成了一个shell命令包,起名叫busybox。






6.rootfs中还应该有什么
 6.1、最重要的就是/linuxrc
 
 6.2、dev目录下的设备文件。在linux中一切皆是文件,因此一个硬件设备也被虚拟化成一个设备文件来访问,在linux系统中/dev/xxx就表示一个硬件设备,
 我们要操作这个硬件时就是open打开这个设备文件,然后read/write/ioctl操作这个设备,最后close关闭这个设备。
 在最小rootfs中/dev目录也是不可少的,这里面有一两个设备文件是rootfs必须的。
 
 6.3、sys和proc目录。在最小rootfs中也是不可省略的,但是这两个只要创建了空文件夹即可,里面是没东西的,也不用有东西。这两个目录也是和驱动有关的。
 属于linux中的虚拟文件系统。
 6.4、usr是系统的用户所有的一些文件的存放地,这个东西将来busybox安装时会自动生成。
 
 6.5、etc目录是很关键很重要的一个,目录中的所有文件全部都是运行时配置文件。/etc目录下的所有配置文件会直接或者间接的被/linuxrc所调用执行,
  完成操作系统的运行时配置。etc目录是制作rootfs的关键,所以后面下一个课程专门讲这个etc目录。
  
 6.6、lib目录也是rootfs中很关键的一个,不能省略的一个。lib目录下放的是当前操作系统中的动态和静态链接库文件。我们主要是为了其中的动态链接库。
 
3.7以上全部内容来自朱老师的课件,感谢一下,套朱老师的话,抄也要抄的光明正大,抄了就要说明一下。


二、根文件系统构建详解(基于训为4412开发板)
 1、busybox源码下载
 (1)busybox是一个开源项目,所以源代码可以直接从网上下载。
 (2)下载busybox可以去linuxidc等镜像网站,也可以去www.busybox.net官方网站下载。
 (3)训为用的busybox版本是1.22.1
 
 2、确认busybox的Makefile中的两个重要参数
 (1) ARCH = arm
 (2) CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin//arm-none-linux-gnueabi-
  
 3、make menuconfig进行配置 
  (1)参考训为的配置
  (2)也可以参考我发上去的配置,来源是朱老师提供的
  
 4、busybox源码简单分析
  4.1、整个程序入口确认
  (1)分析一个程序,不管多庞大还是小,最好的路线都是按照程序运行时的逻辑顺序来。所以找到一个程序的入口至关重要。
  (2)学C语言的时候都知道程序的主函数main函数就是整个程序的入口。这种情况适应于操作系统下工作的应用程序的情况。
  (3)在uboot和linux kernel这两个大的C语言的项目中,main函数都没有,都不是入口。在我们这种裸机程序中入口不是main函数,而是由连接脚本来指定的。
  (4)busybox是linux启动起来后工作的一个应用程序,因此其中必然有main函数,而且main就是入口。
  
 4.2、busybox中main函数全解析
 (1)busybox入口就是main函数,其中有很多个main但是只有一个起作用了,其他的是没起作用的。真正的busybox工作时的入口是libbb/appletlib.c中的main函数
 (2)busubox中有很多xxx_main函数,这些main函数每一个都是busybox支持的一个命令的真正入口。譬如ls_main函数就是busybox当作ls函数使用时的入口程序。
 (3)ls或者cd等命令其实都是busybox一个程序,但是实际执行时的效果却是各自的效果。busybox是如何实现一个程序化身万千还能各自工作的?答案就是main转xxx_main。
   也就是说busybox每次执行时都是先执行其main,在main函数中识别(靠main函数的传参argv[0]来识别)我们真正要执行的函数(譬如ls)然后去调用相应的xxx_main
  (譬如ls_main)来具体实现这个命令。
  
 4.3、inittab解析与执行
  (1)inittab的解析是在busybox/init/init.c/init_main函数中
  (2)执行逻辑是:先通过parse_inittab函数解析/etc/inittab(解析的重点是将inittab中的各个action和process解析出来),
  然后后面先直接执行sysinit和wait和once(注意这里只执行一遍),然后在while(1)死循环中去执行respwan和askfirst。


 4.4、busybox的体积优势原理
  (1)busybox实际上就是把ls、cd、mkdir等很多个linux中常用的shell命令集成在一起了。集成在一起后有一个体积优势:就是busybox程序的大小比
    busybox中实现的那些命令的大小加起来要小很多。
  (2)busybox体系变小的原因主要有2个:第一个是busybox本身提供的shell命令是阉割版的(busybox中的命令支持的参数选项比发行版中要少,
    譬如ls在发行版中可以有几十个-x,但是在busybox中只保留了几个常用的选项,不常用的都删除掉了);第二个是busybox中因为所有的命令的实现代码都在一个程序中实现,
而各个命令中有很多代码函数都是通用的(譬如ls和cd、mkdir等命令都会需要去操作目录,因此在busybox中实现目录操作的函数就可以被这些命令共用),
共用会降低重复代码出现的次数,从而减少总的代码量和体积。
  (3)经过分析,busybox的体积优势是嵌入式系统本身的要求和特点造成的。
 
 5.对比训为提供的最小文件系统进行构建分析
  5.1、inittab详解
  5.1.1、添加一个典型的inittab
   (1)理论讲了一大堆,终于到重点了,由上面可以看出,我们执行linuxrc,即执行了busybox,通过mian函数来到了init_main函数,在这里开始各种初始化的东西。
   (2)其中涉及一个重要的文件,那就是inittab它是由init_main函数指定的文件,奇怪的是训为的最小文件系统制作过程又没有它,那他们提供的最小文件系统是怎么工作的?
   (3)阅读源代码可以发现,若busybox通过parse_inittab函数解析/etc/inittab,发现不存在这个文件时,会自己添加几个必要的的执行命令,可以自己去看。
   (4)将我提供的典型的inittab文件复制到我们制作的rootfs的根目录下的/etc/目录下
   (5)启动内核使用nfs方式挂载这个rootfs看效果
   (6)实验现象是成功启动并且挂载rootfs进入了控制台命令行。当前制作的最小rootfs成功了 

  5.1.2、inittab格式解析
   (1)inittab的工作原理就是被/linuxrc(也就是busybox)执行时所调用起作用。
   (2)inittab在/etc目录下,所以属于一个运行时配置文件,是文本格式的(内容是由一系列的遵照一个格式组织的字符组成的),实际工作的时候busybox会(按照一定的格式)解析这个inittab文本文件,然后根据解析的内容来决定要怎么工作。
   (3)busybox究竟如何完成解析并且解析结果如何去工作(busybox中实现/etc/inittab的原理)并不是我们的目标,我们的重点是inittab的格式究竟怎样的?我们看到一个inittab后怎么去分析这个inittab对启动的影响。
   (4)inittab的格式在busybox中定义的,网上可以搜索到详细的格式说明,具体去参考即可:
   第一个:#开始的行是注释
   第二个:冒号在里面是分隔符,分隔开各个部分。
   第三个:inittab内容是以行为单位的,行与行之间没有关联,每行都是一个独立的配置项,每一个配置项表示一个具体的含义。
   第四个:每一行的配置项都是由3个冒号分隔开的4个配置值共同确定的。这四个配置值就是id:runlevels:action:process。值得注意得是有些配置值可以空缺,
   空缺后冒号不能空缺,所以有时候会看到连续2个冒号。
   第五个:每一行的配置项中4个配置值中最重要的是action和process,action是一个条件/状态,process是一个可被执行的程序的pathname。合起来的意思就是:
   当满足action的条件时就会执行process这个程序。


   注意:理解inittab的关键就是明白“当满足action的条件时就会执行process这个程序。” 你去分析busybox的源代码就会发现,busybox最终会进入一个死循环,
   在这个死循环中去反复检查是否满足各个action的条件,如果某个action的条件满足就会去执行对应的process。


   第六个:明白各个action什么意思
   
 5.2、rcS文件介绍
  5.2.1、/etc/init.d/rcS文件是linux的运行时配置文件中最重要的一个,其他的一些配置都是由这个文件引出来的。这个文件可以很复杂也可以很简单,
   里面可以有很多的配置项。我提供的和训为的就不一样。
  
  5.2.2、PATH=xxx
  (1)首先从shell脚本的语法角度分析,这一行定义了一个变量PATH,值等于后面的字符串
  (2)后面用export导出了这个PATH,那么PATH就变成了一个环境变量。
  (3)PATH这个环境变量是linux系统内部定义的一个环境变量,含义是操作系统去执行程序时会默认到PATH指定的各个目录下去寻找。如果找不到就认定这个程序不存在,
    如果找到了就去执行它。将一个可执行程序的目录导出到PATH,可以让我们不带路径来执行这个程序。
  (4)rcS中为什么要先导出PATH?就是因为我们希望一旦进入命令行下时,PATH环境变量中就有默认的/bin /sbin /usr/bin /usr/sbin 这几个常见的可执行程序的路径,
     这样我们进入命令行后就可以ls、cd等直接使用了。
  (5)为什么我们的rcS文件还没添加,系统启动就有了PATH中的值?原因在于busybox自己用代码硬编码为我们导出了一些环境变量,其中就有PATH。


  5.2.3、runlevel=
  (1)runlevel也是一个shell变量,并且被导出为环境变量。
  (2)runlevel这个环境变量到底有什么用?
  (3)runlevel=S表示将系统设置为单用户模式


  5.2.4、umask=
  (1)umask是linux的一个命令,作用是设置linux系统的umask值。
  (2)umask值决定当前用户在创建文件时的默认权限。


  5.2.5、mount -a
  (1)mount命令是用来挂载文件系统的
  (2)mount -a是挂载所有的应该被挂载的文件系统,在busybox中mount -a时busybox会去查找一个文件/etc/fstab文件,这个文件按照一定的格式列出来所有应该被挂载的文件系统
  (包括了虚拟文件系统)
  (3)训为提供的rcS中的也是一种挂载方法。
  (4)挂载前要创建对应的文件夹

  5.2.6、mdev
  (1)mdev是udev的嵌入式简化版本,udev/mdev是用来配合linux驱动工作的一个应用层的软件,udev/mdev的工作就是配合linux驱动生成相应的/dev目录下的设备文件。
  (2)因为这个问题涉及到驱动,因此详细讲解要等到驱动部分。这里我们只是通过一些直观的现象来初步理解udev/mdev的工作效果。
  (3)在rcS文件中没有启动mdev的时候,/dev目录下启动后是空的;在rcS文件中添加上mdev有关的2行配置项后,再次启动系统后发现/dev目录下生成了很多的设备驱动文件。
  (4)/dev目录下的设备驱动文件就是mdev生成的,这就是mdev的效果和意义。
  
  5.2.7、hostname
  (1)hostname是linux中的一个shell命令。命令(hostname xxx)执行后可以用来设置当前系统的主机名为xxx,直接hostname不加参数可以显示当前系统的主机名。
  (2)/bin/hostname -F /etc/sysconfig/HOSTNAME -F来指定了一个主机名配置文件(这个文件一般文件名叫hostname或者HOSTNAME,然后这个文件里面的内容就是主机名)
     也可以直接/bin/hostname DGY4412 (/bin/hostname xxx)
 
  5.2.8、ifconfig
  (1)有时候我们希望开机后进入命令行时ip地址就是一个指定的ip地址(譬如192.168.1.30),这时候就可以在rcS文件中ifconfig eth0 192.168.1.30
  
 5.3、profile文件和用户登录理论
  5.3.1、profile文件添加
  (1)之前添加了/bin/hostname在/etc/sysconfig/HOSTNAME文件中定义了一个hostname(DGY4412),实际效果是:命令行下hostname命令查到的host名字确实是DGY4412。
    但是问题就是命令行的提示符是没有显示的。
  (2)这个问题的解决就要靠profile文件。将提供的profile文件放入/etc/目录下即可。
  (3)添加了之后的实验现象:命令行提示符前面显示:[0@DGY4412 ]#
   结论是:第一,profile文件起了作用,hostname显示出来了。第二,还有个问题,登录用户名没显示出来。原因就是我们直接进入了命令行而没有做登录。
   等我们添加了用户登录功能,并且成功登陆后这个问题就能解决。
  (4)profile文件工作原理是:profile文件也是被busybox(init进程)自动调用的,所以是认名字的。


  5.3.2、如何看到用户登录界面
  (1)linux中有一个原则就是用一个小程序来完成一个功能。如果我们产品确实需要很复杂的综合型的功能,我们倾向于先使用很多个小程序完成其中的一个功能,
    然后再将这些小程序集成起来完成整个大功能的产品。
  (2)这种集成很多个小程序来完成一个大的功能,有很多种技术实现。譬如shell脚本,还有一些别的技术,譬如linux启动中的inittab。
  (3)因为我们之前intttab中有一个配置项 ::askfirst:-/bin/sh,这个配置项作用就是当系统启动后就去执行/bin/sh,执行这个就会出现命令行。
    因此我们这样的安排就会直接进入命令行而不会出现登录界面。
  (4)我们要出现登录界面,就不能直接执行/bin/sh,而应该执行一个负责出现登录界面并且负责管理用户名和密码的一个程序,busybox中也集成了这个程序
   (就是/bin/login和/sbin/gettty),因此我们要在inittab中用/bin/login或者/sbin/getty去替代/bin/sh。


  5.3.3、用户名和密码的设置
  (1)用户名和密码的设置是和登录程序有关联的,但是/bin/login和/sbin/getty在用户名和密码的管理上是一样的。其实常见的所有的linux系统的用户名和密码
   的管理几乎都是一样的。
  (2)密码一般都是用加密文字的,而不是用明文。意思就是系统中的密码肯定是在系统中的一个专门用来存密码的文件中存储的,用明文存密码有风险,
    因此linux系统都是用密文来存储密码的。

 5.4、用户登录实战
  5.4.1、添加/bin/login到sysinit
  (1)在inittab中修改,去掉/bin/sh,换上ttySAC2::sysinit:/bin/login,则系统启动后出现登录界面。可以输入用户名和密码。
  (2)实验现象:成功出现用户登录界面,但是死活密码不对。


  5.4.2、添加passwd和shadow文件
  (1)为什么用户名和密码不对?因为我们根本没有为root用户设置密码。
  (2)linux系统中用来描述用户名和密码的文件是passwd和shadow文件,这两个文件都在etc目录下。passwd文件中存储的是用户的密码设置,shadow文件中存储的是加密后的密码。
  (3)我们直接复制ubuntu系统中的/etc/passwd和/etc/shadow文件到当前制作的rootfs目录下,然后再做修改即可。
  (4)/etc/passwd和/etc/shadow修理好后,shadow中默认有一个加密的密码口令,这个口令和你拷贝的shadow本身有关,像我的ubuntu中root用户的密码就是root,
   因此复制过来后登陆时的密码还是root。


  5.4.3、重置密码实践 
  (1)ubuntu刚装好的时候默认登录是用普通用户登录的,默认root用户是关闭的。普通用户的密码是在装系统的时候设置的,普通用户登陆后可以使用su passwd root给root用户
    设置密码,设置了密码后root用户才可以登录。
  (2)其实这个原因就是root用户在/etc/shadow文件中加密口令是空白的。所以是不能登录的。
  (3)busybox中因为没有普通用户,所以做法是:默认root用户如果加密口令是空的则默认无密码直接登录。等我们登陆了之后还是可以用passwd root给root用户设置密码。
  (4)平时有时候我们忘记了自己的操作系统的密码,怎么办?有一种解决方法就是用其他系统(WindowsPE系统或者ubuntu的单用户模式等···)来引导启动,
    启动后挂载到我们的硬盘上,然后找到/etc/shadow文件,去掉密文密码后保存。然后再重启系统后密码就没了。


  5.4.4、getty实战
  (1)大家后面做项目会发现,inittab中最常见的用于登录的程序不是/bin/login,反而是/sbin/getty。
  (2)这两个的差别不详,但是在busybox中这两个是一样的。这两个其实都是busybox的符号链接而已。因此不用严格区分这两个
  (3)我们可以在inittab中用getty替换login程序来实现同样的效果。
  (4)ttySAC2::respawn:/sbin/getty -L ttySAC2 115200 vt100
  
 5.5、动态链接库的拷贝 
  (1)复制命令:cp -rdf /usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib/* ./
  (2)加上参数-rdf的目的是保证符号链接复制过来还是符号链接,而不是变成文件。
  
 5.6、这里的实验步骤可能有点乱,可以看 《最小文件系统制作所需资料 》
  
 以上内容复制粘贴朱老师课件,在此声明 。再次感谢朱老师。有兴趣可以去了解一下《朱老师物联网大讲堂》
 
 2018/2/29
 DGY(改)

猜你喜欢

转载自blog.csdn.net/DGY1223/article/details/80505916
今日推荐