zoukankan      html  css  js  c++  java
  • 《构建根文件系统(四)编译配置busybox》

    1.配置编译busybox

      busybox的官方网站是:http://www.busybox.net/

      打开busybox中的INSTALL文档,里面详细说明了如何配置编译busybox。

      The BusyBox build process is similar to the Linux kernel build:

         make menuconfig     # This creates a file called ".config"
         make                # This creates the "busybox" executable
      

       生成两个可执行文件busybox和busybox_unstripped。

         make install        # or make CONFIG_PREFIX=/path/from/root install (在新得busybox中会在当前目录生成_install,在旧版的busybox最好是通过指定路径,毕竟破坏原有的文件系统)
      

       会在当前目录生成_install文件。

      cd _install

      

     
      注意需要配置一下使用的交叉编译器
      
      具体实现编译可以参考:tiny4412编译配置
     
      也可以通过make menuconfig来改变make install后生成文件的位置,这样就可以指定到我们创建好的目录,不用后面再移。
      make menuconfig 
      Busybox Settings —> 
      Installation Options (“make install” behavior) —> 
      
    2.构建最小根文件系统
      1.创建console和null节点
      内核启动init进程时已经打“/dev/console”设备作为控制台,一般情况下Busybox init程序就使用/dev/console。但是如果内核启动init进程的同时设置了环境变量CONSOLE或console,则使用环境变量所指定的设备。在Busybox init程序中,还会检查这个设备是否打开,如果不能则打开“/dev/null”。所以要创建“/dev/console”和"/dev/null"
      mkdir  /dev
      cd  /dev
      sudo mknod console c 5 1
      sudo mknod null c 1 3
      
      2.构建/etc目录
      mkdir /etc
      vi /etc/inittab
      在inittab中添加    ::askfirst:-/bin/sh
     
      3.安装c库

      (1)我们在busybox设置的是动态链接库,而且编译器是arm-linux-gcc,找到安装arm-linux-gcc的安装路径

      which arm-linux-gcc

      /opt/FriendlyARM/toolschain/4.5.1/bin/arm-linux-gcc上面是我的路径,/opt/FriendlyARM/toolschain/4.5.1/arm-none-linux-gnueabi/lib,这个就是要复制出来的动态库的路径,把里面的动态链接文件复制到filesystem文件夹下

      (2)复制动态链接文件

      cp /opt/FriendlyARM/toolschain/4.5.1/arm-none-linux-gnueabi/lib/.so*  ./lib   -d(因为我们只需要动态库) (-d:若来源文件为连结文件的属性(link file),则复制连结文件属性而非档案本身)

      以上就已经配置完成一个最小的根文件系统,可以使用nfs直接挂载到开发板上。也可以制作成映像文件烧录到开发板中。

    3.完善根文件系统

      1.完善配置initatab
      上一节分析了busybox的源码,知道initatab的作用和里面的内容。可以查看分析busybox源码。
      需要注意的一点是:id:runlevels:action:process是四个配置项,即使有些配置项不需要,但是不能省略冒号,这也就是为什么有时候看到“::”。
      注意:理解inittab的关键就是明白“当满足action的条件时就会执行process这个程序。” 去分析busybox的源代码就会发现,busybox最终会进入一个死循环,在这个死循环中去反复检查是否满足各个action的条件,如果某个action的条件满足就会去执行对应的process。
      
    ::sysinit:/etc/init.d/rcS        //在控制台初始化之前执行rcS,是一个初始化配置脚本。首先被运行。
    ttySAC0::askfirst:-/bin/sh       //在shell前加一个'-'前缀表示是一个登陆shell,指定登陆到哪个tty。
    ::ctrlaltdel:-/sbin/reboot       //按下组合键“ctrl+alt+del”,重启Linux系统
    ::shutdown:/bin/umount -a -r        //系统关机时,卸载所有文件系统
    ::restart:/sbin/init                 //重启init进程

      

      2.创建/etc/init.d/rcS

      这是一个脚本文件,可以在里面添加想自动执行的命令。

    #!/bin/sh
    PATH=/sbin:/bin:/usr/sbin:/usr/bin     #初始化环境变量PATH,操作系统执行程序默认到PATH指定的目录下寻找该程序
    
    runlevel=S  #将系统设置为单用户模式
    prevlevel=N #将系统设置为单用户模式
    
    umask 022#指定当前用户在创建文件时的默认权限 
    
    export PATH runlevel prevlevel  #导出环境变量
    
    mount -a                 #挂载/etc/fstab文件中指定的文件系统
    
    echo /sbin/mdev > /proc/sys/kernel/hotplug
    mdev -s       #生成相应的/dev目录下的设备文件
    
    #从/etc/sysconfig/HOSTNAME文件中读取主机名,命令行下运行hostname即可显示当前系统的主机名
    /bin/hostname -F /etc/sysconfig/HOSTNAME  

      手工创建/etc/sysconfig/HOSTNAME文件,并在其中写入主机名。

    xxxLinux   //自定义主机名

      

      (1)PATH=xxx
      首先从shell脚本的语法角度分析,这一行定义了一个变量PATH,值等于后面的字符串。
      后面用export导出了这个PATH,那么PATH就变成了一个环境变量。
      PATH这个环境变量是linux系统内部定义的一个环境变量,含义是操作系统去执行程序时会默认到PATH指定的各个目录下去寻找。如果找不到就认定这个程序不存在,如果找到了就去执行它。将一个可执行程序的目录导出到PATH,可以让我们不带路径来执行这个程序。
     
      rcS中为什么要先导出PATH?
      就是因为我们希望一旦进入命令行下时,PATH环境变量中就有默认的/bin /sbin /usr/bin /usr/sbin 这几个常见的可执行程序的路径,这样我们进入命令行后就可以ls、cd等直接使用了。
      为什么我们的rcS文件还没添加,系统启动就有了PATH中的值?
    原因在于busybox自己用代码硬编码为我们导出了一些环境变量,其中就有PATH。
     
      (2)runlevel=
      runlevel也是一个shell变量,并且被导出为环境变量。
      runlevel这个环境变量到底有什么用? 
      Linux操作系统自从开始启动至启动完毕需要经历几个不同的阶段,这几个阶段就叫做runlevel。例如init 0就是关机,init 6 就是重启
      Linux系统有7个运行级别(runlevel)
      运行级别0:系统停机状态,系统默认运行级别不能设为0,否则不能正常启动 
      运行级别1:单用户工作状态,root权限,用于系统维护,禁止远程登陆
      运行级别2:多用户状态(没有NFS)
      运行级别3:完全的多用户状态(有NFS),登陆后进入控制台命令行模式
      运行级别4:系统未使用,保留
      运行级别5:X11控制台,登陆后进入图形GUI模式
      运行级别6:系统正常关闭并重启,默认运行级别不能设为6,否则不能正常启动
      runlevel=S表示将系统设置为单用户模式
     
      (3)umask=
      umask是linux的一个命令,作用是设置linux系统的umask值。
      umask值决定当前用户在创建文件时的默认权限。
     
      (4)mount -a
      mount命令是用来挂载文件系统的.
      mount -a是挂载所有的应该被挂载的文件系统,在busybox中mount -a时busybox会去查找一个文件/etc/fstab文件,这个文件按照一定的格式列出来所有应该被挂载的文件系统  (包括了虚拟文件系统)

      (5)mdev -s
      mdev是udev的嵌入式简化版本,udev/mdev是用来配合linux驱动工作的一个应用层的软件,udev/mdev的工作就是配合linux驱动生成相应的/dev目录下的设备文件。
      在rcS文件中没有启动mdev的时候,/dev目录下启动后是空的;
      

       在rcS文件中添加以下与mdev有关的2行配置项后,

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

      再次启动系统后发现/dev目录下生成了很多的设备驱动文件。

      

      /dev目录下的设备驱动文件就是mdev生成的,这就是mdev的效果和意义。

      (6)hostname  
      hostname是linux中的一个shell命令。hostname xxx执行后可以设置当前主机名为xxx ,直接hostname不加参数可以显示当前系统的主机名。
      /bin/hostname -F /etc/sysconfig/HOSTNAME
      指定了一个主机名配置文件(这个文件一般文件名叫hostname或者HOSTNAME)
      
      根据/bin/hostname -F /etc/sysconfig/HOSTNAME,在etc下创建sysconfig 
      

      在sysconfig/下创建 HOSTNAME,直接输入主机名:Aliya

      

      重启,发现没有显示用户名和hostname ,怎么解决?

      注意:不设置HOSTNAME,默认的是一个ip地址,在我实验的时候是 192.168.1.10

      添加profile文件后,即可显示用户名和hostname

     

      3.创建/etc/fstab

      “执行mount  -a”命令后挂载proc、sysfs、tmpfs文件系统

    # /etc/fstab: static file system information.
    #
    # Use 'vol_id --uuid' to print the universally unique identifier for a
    # device; this may be used with UUID= as a more robust way to name devices
    # that works even if disks are added and removed. See fstab(5).
    #
    # <file system>   <mount point>   <type>   <options>              <dump>         <pass>
    proc              /proc              proc       defaults              0                0
    sysfs          /sys              sysfs       defaults              0                0
    tmpfs               /var              tmpfs       defaults              0                0
    tmpfs               /tmp              tmpfs       defaults              0                0
    tmpfs               /dev              tmpfs       defaults              0                0

      为保证挂载成功,在根目录下手工创建/proc、/sys、/var、/tmp、/dev目录。

      

      4.创建/etc/profile

       profile文件也将被linuxrc进程调用,在Linux终端命令行提示符中显示主机名。
    # Ash profile
    # vim: syntax=sh
    
    # No core files by default
    ulimit -S -c 0 > /dev/null 2>&1
    
    USER="`id -un`"
    LOGNAME=$USER
    PS1='[u@h W]# '
    PATH=$PATH
    
    HOSTNAME=`/bin/hostname`
    
    export USER LOGNAME PS1 PATH

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

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

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

      

      结论是:第一,profile文件起了作用,hostname显示出来了。

      还有个问题,登录用户名没显示出来。

      原因就是我们直接进入了命令行而没有做登录。等我们添加了用户登录功能,并且成功登陆后这个问题就能解决。

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

      5.添加用户登录文件(passwd、shadow文件)

      passwd文件中存储的是用户的密码设置,shadow文件中存储的是加密后的密码。

      直接复制ubuntu系统中的/etc/passwd和/etc/shadow文件到当前制作的根目录下,然后再做修改即可。

      修改后passwd文件内容如下:

    root:x:0:0:root:/root:/bin/sh     #登录成功后,进入/root目录

      修改后passwd文件内容如下:

    root::17680:0:99999:7:::     #root用户密码为空

      在根目录下创建/root目录。重新启动即可使用 root 登录,登录后使用 passwd root 命令设置用户密码。

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

      因为我们之前intttab中有一个配置项 ::askfirst:-/bin/sh,这个配置项作用就是当系统启动后就去执行/bin/sh,执行这个就会出现命令行。因此我们这样的安排就会直接进入命令行而不会出现登录界面。

      我们要出现登录界面,就不能直接执行/bin/sh,而应该执行一个负责出现登录界面并且负责管理用户名和密码的一个程序,busybox中也集成了这个程序(就是/bin/login和/sbin/gettty),因此我们要在inittab中用/bin/login或者/sbin/getty去替代/bin/sh。

      

  • 相关阅读:
    Linux 02
    Linux 01
    React 函数式组件的 Ref 和子组件访问(useImperativeHandle)
    排序算法之 Java插入排序算法
    排序算法之 Java选择排序算法
    排序算法之 Java冒泡算法
    类加载的过程---验证和准备
    类加载的过程---加载
    mysql explain 查询处理的结果详解
    springboot整合分布式缓存hazelCast
  • 原文地址:https://www.cnblogs.com/zhuangquan/p/11566075.html
Copyright © 2011-2022 走看看