S5PV210Kernel移植9之rootfs的busybox构建

1.busybox源码下载

1)busybox是一个开源项目,所以源代码可以直接从网上下载。

2)busybox的版本差异不大,版本新旧无所谓。

3)下载busybox可以去linuxidc等镜像网站,也可以去www.busybox.net官方网站下载。

2.修改Makefile

1)ARCH = arm

2)CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-

3make menuconfig进行配置

Busybox Settings--->

         Build Options--->

                   [*]Build BusyBox as a static binary(no shared libs)

Busybox Library Tuning--->

         [*]vi-style line editing commands

         [*]Fancy shell prompts

Linux Module Utilities--->

         [ ]Simplified modutils

         [*]insmod

         [*]rmmod

         [*]lsmod

         [*]modprobe

         [*]depmod

Linux System Utilities--->[*]mdev

         [*]Support /etc/mdev.conf

         [*]Support subdirs/symlinks

         [*]Support regular expressions substitutions when renaming dev

         [*]Support command execution at device addition/removal

         [*]Support loading of firmwares169.4        make 然后 make install

1)make编译,如果有错误解决之

http://www.jianshu.com/p/717472476071

2)make install执行的时候其实是在执行busybox顶层目录下的一个目标install。

3)make install在所有的linux下的软件中作用都是安装软件。在传统的linux系统中安装软件时都是选择源代码方式安装的。我们下载要安装的软件源代码,然后配置、编译、安装。make install的目的就是将编译生成的可执行程序及其依赖的库文件、配置文件、头文件安装到当前系统中指定(一般都可以自己指定安装到哪个目录下,如果不指定一般都有个默认目录)的目录下

4.设置bootargs挂载添加了busybox移植的rootfs

1)之前建立了一个空的文件夹然后自己touch linuxrc随便创建了一个不能用的/linuxrc然后去nfs挂载rootfs,实验结果是:挂载成功,执行/linuxrc失败。

2)现在我们移植了busybox后/linuxrc就可以用了,然后再次去nfs挂载这个rootfs。预计看到的效果是:挂载成功,执行/linuxrc也能成功。

3)编译时候要指定busybox的安装位置。

4)编译成功标志是出现busybox,然后make install。

5)注意uboot的bootargs设置成:setenv bootargs root=/dev/nfs nfsroot=192.168.1.3:/root/porting_x210/rootfs/rootfs ip=192.168.1.100:192.168.1.3:192.168.1.1:255.255.255.0::eth0:off  init=/linuxrc console=ttySAC2,115200

6)实验结果:挂载成功,执行/linuxrc(也就是busybox)成功,但是因为找不到/etc/init.d/rcS和/dev/tty2等文件所以一直在打印错误提示信息,但是其实有进入命令行。

5.inittab详解

5.1添加一个典型的inittab

1)将我提供的典型的inittab文件复制到我们制作的rootfs的根目录下的/etc/目录下

2)再次启动内核挂载这个rootfs看效果

3)实验现象是成功启动并且挂载rootfs进入了控制台命令行。当前制作的最小rootfs成功了

5.2inittab格式解析

1)inittab的工作原理就是被/linuxrc(也就是busybox)执行时所调用起作用。

2)inittab在/etc目录下,所以属于一个运行时配置文件,是文本格式的(内容是由一系列的遵照一个格式组织的字符组成的),实际工作的时候busybox会(按照一定的格式)解析这个inittab文本文件,然后根据解析的内容来决定要怎么工作。

3)busybox究竟如何完成解析并且解析结果如何去工作(busybox中实现/etc/inittab的原理)并不是我们的目标,我们的重点是inittab的格式究竟怎样的?我们看到一个inittab后怎么去分析这个inittab对启动的影响。

4)inittab的格式在busybox中定义的,网上可以搜索到详细的格式说明,具体去参考即可:

#first:run the system script file

::sysinit:/etc/init.d/rcS

::askfirst:-/bin/sh

::ctrlaltdel:-/sbin/reboot

#umount all filesystem

::shutdown:/bin/umount -a -r

#restart init process

::restart:/sbin/init

第一个:#开始的行是注释

第二个:冒号在里面是分隔符,分隔开各个部分。

第三个:inittab内容是以行为单位的,行与行之间没有关联,每行都是一个独立的配置项,每一个配置项表示一个具体的含义。

第四个:每一行的配置项都是由3个冒号分隔开的4个配置值共同确定的。这四个配置值就是id:runlevels:action:process。值得注意得是有些配置值可以空缺,空缺后冒号不能空缺,所以有时候会看到连续2个冒号。

第五个:每一行的配置项中4个配置值中最重要的是action和process,action是一个条件/状态,process是一个可被执行的程序的pathname合起来的意思就是:当满足action的条件时就会执行process这个程序。

id:runlevels:action:process

⑴ id 字段:由 1-4 个字符组成,用来唯一标识条目。

⑵ runlevels 字段:运行级别,用来指定该条目适用于哪个运行级别。如果该字段为空,代表适用于 0 — 6 的运行级别。

⑶ action 字段:操作,允许的操作如下

⑷ process 字段:该条目所要执行的进程,可以是任何合法的 shell 命令。

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

第六个:明白各个action什么意思

⑶ action 字段:操作,允许的操作如下:

    ⒈respawn    如果 process 字段指定的进程不存在,就启动该进程,init 不会等待处理结束,而是继续扫描 inittab 文件。当该进程被终止时,init 将重新启动它。如果相应的进程已经存在,init 就忽略该条目并继续扫描inittab 文件。

    ⒉wait        启动进程并等待处理结束,处理结束后才去处理下一条条目。

    ⒊once        启动进程,不会等待处理结束,而是继续处理下一条条目。当该进程被终止时,init 不会重新启动它。从一个运行级别进入另一个运行级别时,如果相应的进程仍在运行,init 就不会重新启动该进程。

    ⒋boot        只在系统启动时,init 才处理这条条目,启动相应的进程,并不等待处理结束就去处理下一条条目。当这样的进程终止时,也不会重新启动它。

    ⒌bootwait    系统启动后,当第一次从单用户模式进入多用户模式时才处理该条目,init 启动这样的进程,并且等待其处理结束才处理下一条条目,当该进程被终止时,也不重新启动它。

    ⒍off        如果相应的进程正在运行,那么就发出一个警告信号,等待数秒后,再发出信号 SIGKILL 强制终止该进程。如果相应的进程不存在就忽略该条目。

    ⒎ondemand    与“respawn”的功能一样,但是只适用于运行级别为 A、B、C 的条目。

    ⒏initdefault    指定一个默认的运行级别,如果指定了多个运行级别,其中最大的数字将是默认的运行级别。如果 inittab 文件没有包含该条目,在系统启动时会请求用户为其指定一个默认的运行级别。

    ⒐sysinit    指定的进程在访问控制台之前执行,这样的条目仅用于对某些设备的初始化,目的是为了使 init 在这样的设备上向用户提问有关运行级别的问题,init 需要等待进程运行结束后才继续。

    ⒑powerwait    当 init 接到断电的信号时,处理指定的进程,并且等到处理结束后才去检查其他的条目。

    ⒒powerfail    当 init 接到断电的信号时,处理指定的进程,但是不等待该进程处理结束。

    ⒓powerokwait

    ⒔powerfailnow

    ⒕ctrlaltdel    当 init 收到信号时,执行指定进程。用来设置 Ctrl + Alt + Delete 组合键的功能。

⒖kbrequest

action

 含义

 sysinit

 为init提供初始化命令脚本的路径

 respawn

 每当相应的进程终止执行时,重新启动该进程

 askfirst

 类似respawn,主要用途是减少系统上执行的终端应用程序的数量。它将会促使init在控制台上显示“Please press Enter to active this console”的信息,并在重新启动进程之前等待用户按下“enter”键

 wait

 告诉init必须等到相应的进程执行完成之后才能继续执行

 once

 仅执行相应的进程一次,而且不会等待它执行完成

 ctratldel

 当按下Ctrl+Alt+Delete组合键时,执行相应的进程

 shutdown

 当系统关机时,执行相应的进程

 restart

 当init重新启动时,执行相应的进程,通常此处所执行的进程就是init本身

 

6.busybox源码分析

6.1整个程序入口确认

1)分析一个程序,不管多庞大还是小,最好的路线都是按照程序运行时的逻辑顺序来。所以找到一个程序的入口至关重要。

2)学C语言的时候都知道程序的主函数main函数就是整个程序的入口。这种情况适应于操作系统下工作的应用程序的情况。

3)在uboot和linux kernel这两个大的C语言的项目中,main函数都没有,都不是入口。在我们这种裸机程序中入口不是main函数,而是由连接脚本来指定的。

4)busybox是linux启动起来后工作的一个应用程序,因此其中必然有main函数,而且main就是入口。

6.2busyboxmain函数全解析

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)来具体实现这个命令。

6.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。

6.4.pwd命令执行路径分析

根据上节讲的,我们在busybox命令行下执行pwd命令时实际执行的是pwd_main这个函数。

7.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的体积优势是嵌入式系统本身的要求和特点造成的。

8.rcS文件介绍

#!/bin/sh

PATH=/sbin:/bin:/usr/sbin:/usr/bin

runlevel=S

prevlevel=N

umask 022

export PATH runlevel prevlevel

mount -a

echo /sbin/mdev > /proc/sys/kernel/hotplug

mdev -s

/bin/hostname -F /etc/sysconfig/HOSTNAME

ifconfig eth0 192.168.1.100

8.1/etc/init.d/rcS文件是linux的运行时配置文件中最重要的一个,其他的一些配置都是由这个文件引出来的。这个文件可以很复杂也可以很简单,里面可以有很多的配置项。

8.2PATH=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。

8.3runlevel=

1)runlevel也是一个shell变量,并且被导出为环境变量。

2)runlevel这个环境变量到底有什么用?

linux操作系统自从开始启动至启动完毕需要经历几个不同的阶段,这几个阶段就叫做runlevel,同样,当linux操作系统关闭时也要经历另外几个不同的runlevel,下面我们就准备详细介绍一下runlevel,并向您展示一些小技巧来让您的linux系统避免不必要的重启动。

runlevel可以认为是系统状态,形象一点,您可以认为runlevel有点象微软的windows操作系统中的Normal,safemode,和Command prompt only。进入每个runlevel都需要启动或关闭相应的一系列服务(services),这些服务(services)以初始化脚本的方式放置于目录/etc/rc.d/rc?.d/或者/etc/rc?.d下面(?代表runlevel的对应序号)

在大多数的linux发行版本中,通常有8个runlevel

Runlevel  System State

0  Halt the system

1   Single user mode

2  Basic multi user mode

3  Multi user mode

5  Multi user mode with GUI

6  Reboot the system

S, s  Single user mode

多数的桌面的linux系统缺省的runlevel是5,用户登陆时是图形界面,而多数的服务器版本的linux系统缺省的runlevel是3,用户登陆时是字符界面,runlevel 1和2除了调试之外很少使用,runlevel s和S并不是直接给用户使用,而是用来为Single user mode作准备。

linux的运行模式比起windows的启动模式的优势在于:你可以在系统空闲时使用.init工具切换你现在使用的runlevel,另外,当你关闭或者启动linux系统时你已经不知不觉中切换你的runlevel,系统关机进程需要调用runlevel(0或6)来关闭所有正在运行中的进程。

3)runlevel=S表示将系统设置为单用户模式

------Prevlevel

这是linux中shell的变量,$0只是其中的一个。下面是常用的shell变量: $0 Shell本身的文件名 $1~$n 添加到Shell的各参数值。$1是第1参数、$2是第2参数… $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行的命令

8.4umask=

umask使用方法

  A 什么是umask?

  当我们登录系统之后创建一个文件总是有一个默认权限的,那么这个权限是怎么来的呢?这就是umask干的事情。umask设置了用户创建文件的默认 权限,它与chmod的效果刚好相反,umask设置的是权限“补码”,而chmod设置的是文件权限码。一般在/etc/profile、$ [HOME]/.bash_profile或$[HOME]/.profile中设置umask值。

  你的系统管理员必须要为你设置一个合理的 umask值,以确保你创建的文件具有所希望的缺省权限,防止其他非同组用户对你的文件具有写权限。在已经登录之后,可以按照个人的偏好使用umask命 令来改变文件创建的缺省权限。相应的改变直到退出该shell或使用另外的umask命令之前一直有效。一般来说,umask命令是在/etc /profile文件中设置的,每个用户在登录时都会引用这个文件,所以如果希望改变所有用户的umask,可以在该文件中加入相应的条目。如果希望永久 性地设置自己的umask值,那么就把它放在自己$HOME目录下的.profile或.bash_profile文件中

  B 如何计算umask值

  umask 命令允许你设定文件创建时的缺省模式,对应每一类用户(文件属主、同组用户、其他用户)存在一个相应的umask值中的数字。对于文件来说,这一数字的最 大值分别是6系统不允许你在创建一个文本文件时就赋予它执行权限,必须在创建后用chmod命令增加这一权限。目录则允许设置执行权限,这样针对目录来 说,umask中各个数字最大可以到7。

  该命令的一般形式为:

  umask nnn

  其中nnn为umask置000-777。

  1. umask是linux的一个命令,作用是设置linux系统的umask值。

默认权限的属性上,目录与文件是不一样的。由于我们不希望文件具有可执行的权力,默认情况中,文件是没有可执行(x)权限的。因此:

若用户建立为”文件”则默认“没有可执行(x)项目”,即只有rw这两个项目,也就是最大为666分,默认属性如下:

-rw-rw-rw-

若用户建立为”目录”,则由于x与是否可以进入此目录有关,因此默认为所有权限均开放,即为777分,默认属性如下:

drwxrwxrwx

umask指定的是“该默认值需要减掉的权限”。因为r、w、x分别是4、2、1,所以。也就是说,当要去掉能写的权限,就是输入2,而如果要去掉能读的权限,也就是4,那么要去掉读与写的权限,也就是6,而要去掉执行与写入的权限,也就是3。请问,5是什么?就是读与执行的权限。如果以上面的例子来说明的话,因为umask为022,所以user并没有被去掉属性,不过group与others的属性被去掉了2(也就是w这个属性),那么当用户:

建立文件时:(-rw-rw-rw-) – (-----w--w-) ==> -rw-r--r--

建立目录时:(drwxrwxrwx) – (d----w--w-) ==> drwxr-xr-x

2)umask值决定当前用户在创建文件时的默认权限。

8.5mount -a

1)mount命令是用来挂载文件系统的

2)mount -a是挂载所有的应该被挂载的文件系统,在busybox中mount -a时busybox会去查找一个文件/etc/fstab文件,这个文件按照一定的格式列出来所有应该被挂载的文件系统(包括了虚拟文件系统)

8.6PATH&runlevel

1)我们实战发现rcS文件明明存在但是却提示不存在,问题原因就是rcS文件在windows下创建的,行尾换行符为'\r\n',多了点东西。但是因为ubuntu中的vi对行尾做了优化,所以在ubuntu中是看不出来多了东西的。但是在securecrt下一看就发现每一行末尾多出来了一个^M

2)这个故事告诉我们:shell脚本文件如果格式不对,运行时可能会被提示文件不存在。

3)扩展讲一个:有时候一个应用程序执行时也会提示文件不存在,问题可能是这个程序所调用的一个动态链接库找不到。

4)测试结果:PATH本来在busybox中就已经用代码导出过了,所以rcS中再次导出没有任何明显的现象,因此看不出什么差别;runlevel实际执行结果一直是unknown,问题在于busybox并不支持runlevel这个特性。

8.7.umask测试

1)umask是022的时候,默认touch创建一个文件的权限是644

2)umask是044的时候,默认touch创建一个文件的权限是622

3)umask是444的时候,默认touch创建一个文件的权限是222

总结:umask的规律就是:umask值和默认创建文件的权限值加起来是666.

8.8.mount测试

1)挂载时全部出错:

mount: mounting proc on /proc failed: No such file or directory

mount: mounting sysfs on /sys failed: No such file or directory

mount: mounting tmpfs on /var failed: No such file or directory

mount: mounting tmpfs on /tmp failed: No such file or directory

mount: mounting tmpfs on /dev failed: No such file or directory

2)原因是因为根文件系统中找不到挂载点。所谓挂载点就是我们要将目标文件系统(当然这里都是虚拟文件系统)挂载到当前文件系统中的某一个目录中,这个目录就是挂载点。

3)解决方案就是自己在制作的rootfs根目录下创建这些挂载点目录即可。

4)验证是否挂载成功,可以看挂载时输出信息;还可以启动后去看proc和sys文件夹,如果有文件出现则证明挂载成功了,如果没东西就证明失败了。

9.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的效果和意义。

10.hostname

1)hostname是linux中的一个shell命令。命令(hostname xxx)执行后可以用来设置当前系统的主机名为xxx,直接hostname不加参数可以显示当前系统的主机名。

2)/bin/hostname -F /etc/sysconfig/HOSTNAME -F来指定了一个主机名配置文件(这个文件一般文件名叫hostname或者HOSTNAME)

11.ifconfig

有时候我们希望开机后进入命令行时ip地址就是一个指定的ip地址(譬如192.168.1.30),这时候就可以在rcS文件中ifconfig eth0 192.168.1.30

12.profile文件和用户登录理论

12.1.profile文件添加

1)之前添加了/bin/hostname在/etc/sysconfig/HOSTNAME文件中定义了一个hostname(aston210),实际效果是:命令行下hostname命令查到的host名字确实是aston210。但是问题就是命令行的提示符是没有显示的。

2)这个问题的解决就要靠profile文件。将提供的profile文件放入/etc/目录下即可。

3)添加了之后的实验现象:命令行提示符前面显示:[@aston210 ]#

结论是:第一,profile文件起了作用,hostname显示出来了。第二,还有个问题,登录用户名没显示出来。原因就是我们直接进入了命令行而没有做登录。等我们添加了用户登录功能,并且成功登陆后这个问题就能解决。

4)profile文件工作原理是:profile文件也是被busybox(init进程)自动调用的,所以是认名字的。

12.1.如何看到用户登录界面

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。

12.3用户名和密码的设置

1)用户名和密码的设置是和登录程序有关联的,但是/bin/login和/sbin/getty在用户名和密码的管理上是一样的。其实常见的所有的linux系统的用户名和密码的管理几乎都是一样的。

2)密码一般都是用加密文字的,而不是用明文。意思就是系统中的密码肯定是在系统中的一个专门用来存密码的文件中存储的,用明文存密码有风险,因此linux系统都是用密文来存储密码的。关于密文密码的使用下节课实践时会详细讲。

13.用户登录实战

13.1添加/bin/loginsysinit

1)在inittab中修改,去掉/bin/sh,换上/bin/login,则系统启动后出现登录界面。可以输入用户名和密码。

2)实验现象:成功出现用户登录界面,但是死活密码不对。

13.2添加passwdshadow文件

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。

用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell

“用户名”是代表用户账号的字符串。通常长度不超过8个字符,并且由大小写字母和/或数字组成。登录名中不能有冒号(:),因为冒号在这里是分隔符。为了兼容起见,登录名中最好不要包含点字符(.),并且不使用连字符(-)和加号(+)打头。

“口令”一些系统中,存放着加密后的用户口令字。虽然这个字段存放的只是用户口令的加密串,不是明文,但是由于/etc/passwd文件对所有用户都可读,所以这仍是一个安全隐患。因此,现在许多Linux系统(如SVR4)都使用了shadow技术,把真正的加密后的用户口令字存放到/etc/shadow文件中,而在/etc/passwd文件的口令字段中只存放一个特殊的字符,例如“x”或者“*”。

“用户标识号”是一个整数,系统内部用它来标识用户。一般情况下它与用户名是一一对应的。如果几个用户名对应的用户标识号是一样的,系统内部将把它们视为同一个用户,但是它们可以有不同的口令、不同的主目录以及不同的登录Shell等。

通常用户标识号的取值范围是0~65535。0是超级用户root的标识号,1~99由系统保留,作为管理账号,普通用户的标识号从100开始。在Linux系统中,这个界限是500

“组标识号”字段记录的是用户所属的用户组。它对应着/etc/group文件中的一条记录。

“注释性描述”字段记录着用户的一些个人情况,例如用户的真实姓名、电话、地址等,这个字段并没有什么实际的用途。在不同的Linux系统中,这个字段的格式并没有统一。在许多Linux系统中,这个字段存放的是一段任意的注释性描述文字,用做finger命令的输出。

“主目录”,也就是用户的起始工作目录,它是用户在登录到系统之后所处的目录。在大多数系统中,各用户的主目录都被组织在同一个特定的目录下,而用户主目录的名称就是该用户的登录名。各用户对自己的主目录有读、写、执行(搜索)权限,其他用户对此目录的访问权限则根据具体情况设置。

用户登录后,要启动一个进程,负责将用户的操作传给内核,这个进程是用户登录到系统后运行的命令解释器或某个特定的程序,即Shell。Shell是用户与Linux系统之间的接口。Linux的Shell有许多种,每种都有不同的特点。常用的有sh(BourneShell),csh(CShell),ksh(KornShell),tcsh(TENEX/TOPS-20typeCShell),bash(BourneAgainShell)等。系统管理员可以根据系统情况和用户习惯为用户指定某个Shell。如果不指定Shell,那么系统使用sh为默认的登录Shell,即这个字段的值为/bin/sh

13.3重置密码实践

1)ubuntu刚装好的时候默认登录是用普通用户登录的,默认root用户是关闭的。普通用户的密码是在装系统的时候设置的,普通用户登陆后可以使用su passwd root给root用户设置密码,设置了密码后root用户才可以登录。

2)其实这个原因就是root用户在/etc/shadow文件中加密口令是空白的。所以是不能登录的。

3)busybox中因为没有普通用户,所以做法是:默认root用户如果加密口令是空的则默认无密码直接登录。等我们登陆了之后还是可以用passwd root给root用户设置密码。

4)平时有时候我们忘记了自己的操作系统的密码,怎么办?有一种解决方法就是用其他系统(WindowsPE系统或者ubuntu的单用户模式等•••)来引导启动,启动后挂载到我们的硬盘上,然后找到/etc/shadow文件,去掉密文密码后保存。然后再重启系统后密码就没了。

14.getty实战

1)大家后面做项目会发现,inittab中最常见的用于登录的程序不是/bin/login,反而是/sbin/getty。

2)这两个的差别不详,但是在busybox中这两个是一样的。这两个其实都是busybox的符号链接而已。因此不用严格区分这两个

3)我们可以在inittab中用getty替换login程序来实现同样的效果。

s3c2410_serial2::respawn:/sbin/getty –L s3c2410_serial2 115200 vt100

15.动态链接库的拷贝

15.1静态编译链接helloworld程序并执行

1)任务:自己写一个helloworld程序,然后交叉编译连接,然后丢到开发板根文件系统中,开机后去运行。

2)C程序如果使用gcc来编译则可以在主机ubuntu中运行,但是不能在开发板运行;要在开发板运行需要用arm-linux-gcc来交叉编译,但是这时候就不能在主机ubuntu中运行了。我们可以用file xx命令来查看一个elf可执行程序是哪个架构的。

3)静态链接:arm-linux-gcc hello.c -o hello_satic -static

4)实验结果:静态编译连接后生成的hello_satic已经可以成功运行。

15.2.动态编译连接helloworld程序并执行

1)动态链接:arm-linux-gcc hello.c -o hello_dynamic

2)实验结果:-sh: ./hello_dynamic: not found运行时提示找不到程序。

3)错误分析:动态连接的hello程序中调用到了printf函数,而printf函数在动态连接时要在运行时环境(开发板的rootfs)中去寻找对应的库文件(开发板rootfs中部署的动态链接库中包含了printf函数的那个库文件)。如果找到了则printf函数就会被成功解析,然后hello_dynamic程序就会被执行;如果找不到则程序就不能被执行,命令行会提示错误信息-sh: ./hello_dynamic: not found

4)解决方案:将arm-linux-gcc的动态链接库文件复制到开发板rootfs的/lib目录下即可解决。

15.3找到并复制动态链接库文件到rootfs

1)我们用的arm-2009q3这个交叉编译工具链的动态链接库在/usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib目录下。其他的一些交叉编译工具链中动态链接库的目录不一定在这里,要去找一下。找的方法就是find

2)复制动态链接库到rootfs/lib目录下。复制时要注意参数用-rdf,主要目的就是符号链接复制过来还是符号链接。

复制命令:cp lib/*so* /root/porting_x210/rootfs/rootfs/lib/ -rdf

  1. 现在再去测试./hello_dynamic看看是否可以运行,实验结果是可以运行。

15.4使用strip工具去掉库中符号信息

动态链接库so文件中包含了调试符号信息,这些符号信息在运行时是没用的(调试时用的),这些符号会占用一定空间。在传统的嵌入式系统中flash空间是有限的,为了节省空间常常把这些符号信息去掉。这样节省空间并且不影响运行。

去掉符号命令:arm-linux-strip *so*

实际操作后发现库文件由3.8M变成了3.0M,节省了0.8M的空间。

16开机自启动与主流rcS格式介绍

16.1修改rcS实现开机自启动

1)开机自启动指的是让一些应用程序能够开机后自动执行

2)开机自启动的实现原理就是在开机会自动执行的脚本rcS中添加上执行某个程序的语句代码即可

16.2前台运行与后台运行

1)程序运行时占用了当前的控制台,因此这个程序不结束我们都无法使用控制台,这就叫前台运行。默认执行程序就是前台运行的。

2)后台运行就是让这个程序运行,并且同时让出控制台。这时候运行的程序还能照常运行而且还能够不影响当前控制台的使用。

3)让一个程序后台运行的方法就是 ./xxx &

16.3开机装载驱动等其他开机自动执行

16.4实际开发中rootfsrcS是怎样的

1)我们以X210开发板九鼎科技做的rootfs中rcS部分来分析

2)分析inittab发现:sysinit执行rcS,shutdown时执行rcK。

3)分析/etc/init.d/rcS和rcK文件发现,rcS和rcK都是去遍历执行/etc/init.d/目录下的S开头的脚本文件,区别是rcS传参是start,rcK传参是stop。

4)由此可以分析出来,正式产品中的rcS和rcK都是一个引入,而不是真正干活的。真正干活的配置脚本是/etc/init.d/S??*。这些文件中肯定有一个判断参数是start还是stop,然后start时去做一些初始化,stop时做一些清理工作。

17制作ext2格式的镜像并烧录启动

17.1     确定文件夹格式的rootfs可用

设置bootargs为nfs启动方式,然后从主机ubuntu中做好的文件夹格式的rootfs去启动,然后看启动效果,作为将来的参照物。

17.2     动手制作ext2格式的镜像

dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240

losetup  /dev/loop1 rootfs.ext2

mke2fs -m 0 /dev/loop1 10240

mount -t ext2 /dev/loop1 ./ext2_rootfs/

(2)向./rootfs中复制内容,用cp ../rootfs/* ./ -rf

(3)umount /dev/loop1

losetup -d /dev/loop1

完成后得到的rootfs.ext2就是我们做好的rootfs镜像。拿去烧录即可。

17.3     烧录镜像并设置合适的bootargs

1)使用fastboot烧录制作好的rootfs.ext2到开发板inand中

fastboot flash system rootfs.ext2

烧录完成后重启系统

2)设置bootargs为:set bootargs console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext2

3)启动后发现现象和之前nfs方式启动挂载rootfs后一样的,至此rootfs制作实验圆满完成。

17.4     总结

1)13节课将rootfs的制作步骤和原理已经完全清楚的讲完了

2)制作过程本身如果有文档指导非常容易,非常简单,但是我们学习时侧重于不是rootfs制作本身,而是rootfs工作的原理分析。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值