Linux3.0最小系统移植

2019-07-13 01:36发布

1.创建fl2440内核的工作目录,便于管理查询: 3rdparty:今后移植到ARM开发板上的第三方应用程序软件包 bootloader:u-boot移植代码 crosstool:交叉编译器 drivers:今后写的驱动文件 images:编译出的image文件,如linux内核,根文件系统等 linux:kernel:Linux内核源码路径            roofts:根文件系统目录树路径 program:我们今后自己写的应用程序 2.下载内核和编译 地址:https://www.kernel.org/pub/linux/kernel/v3.x/ 将内核源码下载到文件linux下,然后解压。(这里是源码包,记得要根据自己的开发板打补丁,否则会有很多错,我在fl2440移植遇到的问题的博客里有介绍) 3.修改内核(这里我根据fl2440开发板硬件来修改的) 将该vim arch/arm/mach-s3c2440/mach-smdk2440.c文件中的s3c24xx init clocks(16934400)的晶振改为12000000 将该vim arch/arm/tools/mach-types文件中的s3c2440    362改为s3c2440     1999;将MINI2440      1999改为MINI2440      362 将该vim drivers/tty/serial/samsung.c文件中的ttySAC改为ttyS 修改Makefile中ARCH ?= ${SUBARCH},改为ARCH ?= arm以及CROSS_COMPILE   ?= $(CONFIG_CROSS_COMPILE:"%"=%)改为交叉编译器的路/opt/x-tools/arm920t/bin/arm-arm920t-linux-gnueabi-(这是我自己安装的路径)这后面应该紧跟回车,空格什么的都不能有。 4.内核编译: linux3.0内核有16198个C文件和1223个汇编文件,这一份源码支持了不同的CPU并且包含了大部分硬件的驱动源码。linux的源码编译系统中有一个很巧妙的铁三角关系,导致对每一个特定用途的嵌入式Linux系统image的过程显得没那么复杂。这个铁三角分别是Kconfig、.config和Makefile文件,他们三者之间的关系简单来说就是去饭店点菜:Kconfig是菜单,.config就是你点的菜,Makefile是做法。 然后make s3c2410_defconfig        export TERM=vt100         make menuconfig 如图: 我们选用s3c2440做的SMDK2440开发板,所以其他的开发板里的内容都不选。 在System Type中这里只选如图所示的两个: 我们的交叉编译器使用的是EABI接口,所以这里一定要修改配置,否则跑不起来。 shell脚本:  #!/bin/bash                                                                 
make  mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008040 -n "Linux Kernel" -d arch/arm/boot/zImage linux-s3c2440.bin chmod a+x linux-s3c2440.bin Shell脚本解释说明:
make命令是编译Linux内核源码,编译完成后将生产arch/arm/boot/zImage内核启动文件。
zImage并不能被u-boot的bootm命令启动,而需要使用mkimage工具在其前面加上bootm命令启动内核所需要的64字节(0x40)头信息方可启动,处
理后的文件一般叫做uImage。
mkimage命令是由u-boot编译产生(u-boot-2010.09/tools/mkimage),在编译完成u-boot后我们需要将它以root权限拷贝到系统/bin路径下。

mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008040 -n "Linux Kernel" -d arch/arm/boot/zImage linuxroms3c2440.bin
-A arm
指定ARCH为arm
-O linux指定操作系统(OS)为Linux
-T kernel指定类型(Type)为内核
-C none指定压缩类型为未压缩,zImage里有自解压的代码;
-a 30008000指定Image加载的地址, u-boot下使用tftp命令下载linux内核到内存的相应地址
-e 30008040指定Linux内核的入口地址, uImage的地址在30008000,uImage是在zImage前面加了64字节(0x40)头,所以内核
zImage入口地址为30008040。

-n "Linux Kernel"指定Image的名字
-d arch/arm/boot/zImage指定zImage文件所在位置 linuxrom-s3c2440.bin指定生成的uImage文件名 然后 chmod a+x bulid.sh ./build.sh 5.跟文件系统的制作: 切换到lib目录下下面这个命令用来将/opt/xtools/arm920t路径下除gconv相关的所有动态库(.so)文件拷贝到 find /opt/xtools/arm920t/ -name "*.so*" | grep -v gconv | xargs -i cp -af {} ./ 我这里遇到得问题是在指定的文件里没找到动态库的文件(应该有能指定编译器生成动态库的路径,我没找到,大家可以去尝试找找),所以可以直接到主目下用 find 命令查找,找到正确的路径。 我这里的路径是../../../crosstool/crosstool-ng-1.16.0/.build/arm-arm920t-linux-gnueabi/ -name "*.so*" | grep -v gconv | xargs -i cp -af {} ./ 拷贝过来的文件有些链接可能  失效,所以我们可以创建一个脚本来重新制作符号链接到本地路径下:                       #!/bin/bash # find all the invalid symlink file and remove "./" before it for sf in `find -L -type 1 | cut -d'/' -f2` ; do #parser and get svmlink target file name file=`ls -l $sf | awk -F '/' '{ print $NF }'` # remove invalid symlink file and generate new one rm -f $sf && ln -s $file $sf done 安装busybox,busybox集压了Linux的许多工具和命令,通过下载busybox的源码并配置编译并安装它就会提供这些Linux的基本命令的实现,它们将会被安装到
跟文件系统树的bin、sbin、usr/bin、usr/sbin等路径下。 make menuconfig:按照下图做出修改
Print Utilities:打印机不用的话,里面的全部都不要选,可以节约空间 Mail  Utilities:邮件收发不用的话,里面的全部不要选,可以节约空间 编译安装busybox到根文件系统树路径下:make && make install 出错: 在nandwrite.c文件中将其注释掉了(实在不想深究,不知道是干啥的),然后编译完成。 2019/01/09增加: 三、编译错误解决参考
1、make出现如下错误:
miscutils/nandwrite.c: In function 'nandwrite_main':
miscutils/nandwrite.c:151: error: 'MTD_FILE_MODE_RAW' undeclared (first use in this?function)
miscutils/nandwrite.c:151: error: (Each undeclared identifier is reported only once
miscutils/nandwrite.c:151: error: for each function it appears in.)
scripts/Makefile.build:197: recipe for target 'miscutils/nandwrite.o' failed
make[1]: *** [miscutils/nandwrite.o] Error 1
Makefile:742: recipe for target 'miscutils' failed
make: *** [miscutils] Error 2
 
解决办法:
MTD_FILE_MODE_RAW在/usr/include/mtd/mtd-abi.h中定义。将/usr/include/mtd/mtd-abi.h拷贝到busybox的include文件中。
#gedit miscutils/nandwrite.c 
修改头文件如下:
 #include "libbb.h"
#include "mtd-abi.h"
#include
编译可以通过。
2、继续make,出现如下错误:
util-linux/blkdiscard.c: In function 'blkdiscard_main':
util-linux/blkdiscard.c:72: error: 'BLKSECDISCARD' undeclared (first use in this function)
util-linux/blkdiscard.c:72: error: (Each undeclared identifier is reported only once
util-linux/blkdiscard.c:72: error: for each function it appears in.)
scripts/Makefile.build:197: recipe for target 'util-linux/blkdiscard.o' failed
make[1]: *** [util-linux/blkdiscard.o] Error 1
Makefile:742: recipe for target 'util-linux' failed
make: *** [util-linux] Error 2
 
解决办法:
BLKSECDISCARD在/usr/include/linux/fs.h中定义,方法如上所述,将/usr/include/linux/fs.h拷贝到busybox的include文件中linux下。
#gedit util-linux/blkdiscard.c
修改内容如下:
#include
编译通过。
  切换到根文件系统树路径下,创建符号链接指向busybox程序,如果使用initramfs根文件系统启动需要该命令: ln -s bin/busybox init。在这里我遇到得问题是:busybox安装的相对路径出现了错误,导致链接不成功。所以一定要在busybox的解压目录下,用ls命令来看相对路径如图: linux下所有的东西都是文件,其中设备也是文件。dev下路径存放所有的linux的设备文件,要用root权限执行mknod命令来创建系统必须启动的设备文件节点,其他的设备节点将有mdev动态创建。 创建var路径下文件 var路径会存放系统运行时的一些文件(入系统日志文件/var/log/message),在该路径下创建相应的符号链接到/tmp下。 创建etc路径下文件 Linux在内核自举启动完成后,最后将创建init进程并执行根文件系统中的/init或/initrc程序,改程序解析并执行/etc/inittab配置文件,在此文件中配置了init进程在系统启动要启动那些应用程序。 # mount all the file systems specified in /etc/fstab ::sysinit:/bin/mount -a # Use mdev to auto generate device nod and auto mount SD card and USB storage ::sysinit:/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug ::sysinit:/sbin/mdev -s #make shm, pts,support ::sysinit:/bin/mkdir -p /dev/pts ::sysinit:/bin/mkdir -p /dev/shm ::sysinit:/bin/mount -t devpts devpts /dev/pts #set hostname null::sysinit:/bin/hostname -F /etc/hostname #Enable console logon null::respawn:/sbin/getty -L ttyS0 115200 vt100 #now run any rc scripts, which used to start other application null::wait:/etc/init.d/rcS #system daemon null::respawn:/sbin/syslogd -n null::respawn:/sbin/klogd -n #Stuff to do before rebooting null::shutdown:/bin/killall klogd null::shutdown:/bin/killall syslogd null::shutdown:/bin/umount -a -r 创建etc/fstab文件 Linux下的mount -a命令将自动挂载/etc/fstab文件中指定的所有需要系统自动挂载的文件。在/etc/inittab中会使用改命令在上电时自动挂载相应的文件系统,这里面主要是挂载一些伪文件系统,这些伪文件系统主要是导出Linux内核运行的相关信息,比较重要的tmpfs,sysfs,proc文件系统等 创建hostname文件名 /etc/inittab文件中通过hostname -F /etc/hostname 命令设置主机名 创建系统启动脚本 系统所有的启动脚本我都放在了init.d路径下,接下来就创建这些脚本: /etc/inittab 脚本会使用命令/etc/init.d/rcS启动所有其他的应用程序,改脚本执行/etc/init.d下所有文件名以S开头且后面紧跟至少包括2个字符的文件。 如果我们希望系统启动时自动设置网卡的IP地址,则可以创建一个文件名以S开头且后面紧跟至少包括2个字符的启动脚本,并给执行权限。 今后很多应用程序将会放在/apps分区下,有时我们希望这些程序的启动脚本也存放在该分区下便于管理。这时可以参考rcS脚本的实现机制,让它也执行在/apps/etc下的所有启动脚本。 创建shell的配置文件 在linux服务器上,我们可以通过修改~/.bash_profile或~/.bashrc文件来修改shell的配置文件,如修改PATH,LD_LIBRARY_PATH环境变量等,也可以在里面定义命令别名。在嵌入式环境下,这些Shell的配置保存在/etc/profile文件中。可以创建该文件配置嵌入式环境busybox里的shell(ash) 创建Linux登录账号文件 Linux系统中的登录账号信息保存在/etc/group、 /etc/passwd和/etc/shadow文件中 /etc/group:文件保存用户组信息 /etc/passwd:文件保存用户信息; /etc/shadow:文件保存相应用户的密码; 在根文件系统中创建这些系统账号文件,我只创建root账号 groupname:passwd:gid:members; 第一个字段为用户组名称; 第二个字段为用户组密码,当为x时密码是映射到/etc/gshadow中的,是非逆的; 第三个字段为GID,及组号,为正整数或0,0被付于了root用户组;系统通常会预留一些较靠前的GID给系统虚拟用户之用,每个系统预留的GID都
不同,一般普通用户的GID从500开始; 第四个字段为用户列表,每个用户间用户逗号分隔; /etc/passwd文件
该文件的格式为:
username:password:uid:gid:fullname:homedir:shell
第一个字段为登录用户名
第二个字段为密码,这里设置为x表示密码被映射到/etc/shadow文件中
第三个字段为用户ID(UID)
第四个字段为用户所属组ID(GID)
第五个字段为用户名全称
第六个字段为用户根目录
第七个字段为用户所用shell的类型 /etc/shadow /etc/shadow文件保存了相应帐号的密文,这个文件内容不能直接创建。如果我们想在嵌入式Linux系统中设置root的登录密码为123456,则我们先在自
己的Linux服务器或虚拟机上修改root密码为123456,然后再将Linux服务器或虚拟机上的/etc/shadow文件里root帐号的密码密文部分拷贝出来,创建根
文件系统树里的etc/shadow时将密文部分用这个密文替换。这个过程做完后记得将自己的Linux服务器或虚拟机的root密码还原回去。 root:$6$ty8Kew3ECW4ZtpjR$oRvyYuuB6.KxIQoEwsLd6kxXelEqbKErXlzdKzUsv7QgjrBP5SHlLmfLShZ4sJeQ1V7tHGv3z4B.WdSxD7awE/:17588:0:99999:7::: username:password:last_change:min_change:max_change:warm:failed_expire:expiration:reserved
第一字段:用户名(也被称为登录名),在/etc/shadow中,用户名和/etc/passwd 是相同的,这样就把passwd 和shadow中用的用户记录联系在
一起;这个字段是非空的;
第二字段:密码加密后的密文,这个字段是非空的;
第三字段:上次修改密码的时间;这个时间是从1970年01月01日算起到最近一次修改口令的时间间隔(天数);
第四字段:两次修改密码间隔最少的天数;如果这个字段的值为空,帐号永久可用;
第五字段:两次修改密码间隔最多的天数;如果这个字段的值为空,帐号永久可用;
第六字段:提前多少天警告用户密码将过期;如果这个字段的值为空,帐号永久可用;
第七字段:在密码过期之后多少天禁用此用户;如果这个字段的值为空,帐号永久可用;
第八字段:用户过期日期;此字段指定了用户作废的天数(从1970年的1月1日开始的天数),如果这个字段的值为空,帐号永久可用;
第九字段:保留字段,目前为空,以备将来发展之用; 创建Linux其他文件 在etc路径下创建resolv.conf文件 该文件用来设置Linux系统得DNS服务器;DNS服务器用来将转换成IP地址。 nameserver 114.114.114.114
nameserver 4.2.2.2

在etc创建hosts文件 /etc/hosts文件存放本机静态绑定的域名,如下面在本机上域名localhost就会被解析成127.0.0.1,不需要DNS来做解析。
127.0.0.1 localhost
创建TZ文件 /etc/TZ文件配置了系统的时区 MST7MDT 创建issue文件 /etc/issue文件里存放在console上登录系统时提示的警告信息 Copyright (C) 2012 studio I.o.T Studio<123.com >
Default Logon Username: root Password: 123456
至此Linux根文件系统树所需要的基本文件都已经有了 ,可以烧录了。