嵌入式软件开发培训笔记——嵌入式linux内核与文件系统移植与分析

一、内核的移植配置
内核版本linux2.6.35
1、基本内核配置 
    1).   主Makefile
        ARCH        = arm
        CROSS_COMPILE   = arm-cortex_a8-linux-gnueabi-
     2).    make s5pc100_defconfig
        将s5pc100_defconfig 移动到源码根目录,并改名为.config
        相当于(cp arch/arm/s5pc100_defconfig ./config)
     3).    make menuconfig
        需先安装menuconfig工具 sudo apt-get install libncurses5-dev
     4).    make zImage   arch/arm/boot/zImage
  ================================================================================= 
 2、往内核添加一个自定义模块(驱动)
     1). 添加一个文件 driver/char/hello_driver.c
    #include
    #include
    #include
    MODULE_LICENSE("GPL");
    int hello_init(void)
    {
        printk("hello_init ! \n");
         return 0;
    }
    void hello_exit(void)
    {
         printk("hello_exit ! \n");
    }
    module_init(hello_init);
    module_exit(hello_exit);
    2). 改动driver/char/Makefile
        obj-$(CONFIG_HELLO_DRIVER) += hello_driver.o     //配置变量的使用
    3). 改动driver/char/Kconfig    //Documentation/kbuild/kconfig-language
         config HELLO_DRIVER
         bool "hello driver support"
         default y
         help
             just for testing!!!!!              //配置变量的定义
    4). make menuconfig
        选择对应的条目                                    //配置变量的赋值

二、内核启动分析 
链接脚本:arch/arm/kernel/vmlinux.lds 
1.内核运行的一个文件(汇编) 
/arch/arm/kernel/head.S:ENTRY(stext) 
bl __lookup_processor_type 检查配置编译好的内核是否支持此处理器 
bl __lookup_machine_type 检查配置编译好的内核是否支持此硬件平台 

bl __create_page_tables 内核在开启mmu(用虚拟地址)之前, 
需要先创建页表(虚拟地址和物理地址之前的转化关系) 

ldr r13, __switch_data @ address to jump to after (保存要跳转的地址) 
@ mmu has been enabled 
adr lr, BSYM(__enable_mmu) @ return (PIC) address (开mmu) 
ARM( add pc, r10, #PROCINFO_INITFUNC ) (初始化处理器核心) 

__switch_data:.word __mmap_switched: 
__mmap_switched: 保存地址信息, 初始化8k 栈空间, 清bss段 跳转到C 
b start_kernel 

2. 内核启动(C语言) init/main.c 
start_kernel() 
    |- setup_arch(&command_line); 初始化硬件平台 
    |- 内核各种机制的初始化 
    |- rest_init(); 开启kernel_init()线程 
        |- kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); 
            |- 初始化设备 挂载根文件系统 开启用户空间第一个进程 init_post(); 

3. 内核启动的最后阶段,开启用户第一个进程(init进程) 
init_post(); 
if (execute_command) { 
853 run_init_process(execute_command); 
854 printk(KERN_WARNING "Failed to execute %s. Attempting " 
855 "defaults...\n", execute_command); 
856 } 
857 run_init_process("/sbin/init"); 
858 run_init_process("/etc/init"); 
859 run_init_process("/bin/init"); 
860 run_init_process("/bin/sh"); 

这一段代码最后都会指向 busybox的应用,busybox里集成了包括init进程 
sh等系统级应用。 
源码可在http://busybox.net/downloads/ 获取 

三、init进程(参考:busybox_src/init/init.c)
1. 打开、解析并运行inittab脚本 (参考:busybox_src/examples/inittab)
    open(/etc/inittab)
2. inittab脚本
   四个域,分别被 :隔开  ××:××:××:××
   Format for each entry: :::
 
    id:  process依赖的终端
    runlevels:运行等级 (busybox不支持)
    action:   process执行的方法
    process:  可执行的内容(应用、脚本)
 
    ::respawn:/bin/sh    
    运行sh  sh在运行时会读配置文件/etc/profile运行
   
    ::sysinit:/etc/init.d/rcS
3. 挂载文件系统
    mount -a  (需要/etc/fstab脚本支持)
4. 创建设备节点
    mdev -s
5. 添加动态库

四、内核的移植(DM9000网卡驱动)
    1、平台代码修改

    vim  arch/arm/mach-s5pc100/mach-smdkc100.c

    2、添加需要的头文件

    #if defined (CONFIG_DM9000)

    #include

    #include

    #endif

    3、平台设备的添加

    /* DM9000 Support */

    #if  defined(CONFIG_DM9000)

    static struct resource dm9000_resources[] = {

            [0] = {

                .start        = 0x88000000,

                .end         = 0x88000000 + 0x3,

                .flags        = IORESOURCE_MEM,

            },

            [1] = {

                .start        = 0x88000000 + 0x4,

                .end        = 0x88000000 + 0x4 +0x3,

                .flags        = IORESOURCE_MEM,

            },

            [2] = {

                .start = IRQ_EINT(10),

                .end   = IRQ_EINT(10),

                .flags        = IORESOURCE_IRQ | IRQ_TYPE_LEVEL_HIGH,

            },

    };

    static struct dm9000_plat_data s5pc100_dm9000_platdata = {

            .flags        =   DM9000_PLATF_16BITONLY,

            .dev_addr[0]  = 0x00,

            .dev_addr[1]  = 0x00,

            .dev_addr[2]  = 0x3e,

            .dev_addr[3]  = 0x26,

            .dev_addr[4]  = 0x0a,

            .dev_addr[5]  = 0x00,

    };

    static struct platform_device s5pc100_device_dm9000 = {

            .name        = "dm9000",

            .id        = -1,

            .num_resources        = ARRAY_SIZE(dm9000_resources),

            .resource        = dm9000_resources,

            .dev = {

                    .platform_data  = & s5pc100_dm9000_platdata,

            }

    };

    #endif

    4、平台设备列表的添加:

    在smdkc100_device[]结构体数组中添加如下内容:

    #if  defined(CONFIG_DM9000)

    &s5pc100_device_dm9000,

    #endif
    5、配置内核
    $ make menuconfig
    1)网络配置:

    [*] Networking support (NEW)  --->

        Networking options  --->

            <*> Packet socket

            <*> Unix domain sockets

            [*] TCP/IP networking

            [*]   IP: multicasting

            [*]   IP: kernel level autoconfiguration

            [*]     IP: BOOTP support

    2)网卡驱动配置

    Device Drivers  ---> 

        [*] Network device support  --->

            [*]   Ethernet (10 or 100Mbit)  --->

                <*>   DM9000 support

    3)网络文件系统的配置

    File systems  ---> 

        [*] Network File Systems  --->

            <*>   NFS client suppor

            [*]     NFS client support for NFS version 3 

            [*]       NFS client support for the NFSv3 ACL protocol extension

            [*]     Root file system on NFS
    6、编译内核,并拷贝到tftpboot目录下

        $ make  zImage

        $ cp arch/arm/boot/zImage  /tftpboot

    7、启动开发板,修改内核启动参数,通过NFS方式挂载根文件系统

五、文件系统的移植
    1、源码下载

        我们选择的版本是busybox-1.17.3.tar.bz2下载路径为:http://busybox.net/downloads/

    2、解压源码

        $ tar  xvf  busybox-1.17.3.tar.bz2

    3、进入源码目录

        $ cd  busybox-1.17.3

    4、配置源码

        $ make menuconfig

        Busybox Settings --->

            Build Options --->

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

                [ ] Force NOMMU build

                [ ] Build with Large File Support (for accessing files > 2 GB)

                (arm-cortex_a8-linux-gnueabi-) Cross Compiler prefix

                () Additional CFLAGS

    5、编译

        $ make

    6、安装

        busybox默认安装路径为源码目录下的_install

        $ makinstall

    7、进入安装目录下

        $ cd  _install

        $ ls

        bin  linuxrc  sbin  usr

    8、创建其他需要目录

        $ mkdir  dev  etc  mnt  proc  var  tmp  sys  root

    9、添加库

        将工具链中的库拷贝到_install目录下

            $ cp  /home/linux/toolchain/arm-none-linux-gnueabi/libc/lib   ./  -a

        删除_install/lib下的所有目录、.o文件和.a文件

        对库进行瘦身以减小文件系统的大小

            $ arm-none-linux-gnueabi-strip  lib/*

    10、添加系统启动文件

        10.1、在etc下添加文件inittab,文件内容如下:

        #this is run first except when booting in single-user mode.

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

        # /bin/sh invocations on selected ttys

        # start an "askfirst" shell on the console (whatever that may be)

        ::askfirst:-/bin/sh

        # stuff to do when restarting the init process

        ::restart:/sbin/init

        # stuff to do before rebooting

        ::ctrlaltdel:/sbin/reboot

 

        10.2、在etc下添加文件fstab文件内容如下:

        #device     mount-point     type        options         dump     fsck order

        proc         /proc             proc           defaults     0                0

        tmpfs         /tmp                   tmpfs         defaults         0                 0

        sysfs           /sys                    sysfs           defaults           0                 0

        tmpfs     /dev                   tmpfs         defaults         0                 0

       这里我们挂的文件系统有三个procsysfstmpfs在内核中procsysfs默认都支持,而tmpfs是没有支持的,我们需要添加tmpfs的支持。

        修改内核配置:

        File systems --->

               Pseudo filesystems --->

                      [*] Virtual memory file system support (former shm fs)

                      [*] Tmpfs POSIX Access Control Lists

        重新编译内核

        10.3、etc下创建init.d目录,并在init.d下创建rcS文件,rcS文件内容为:

            #!/bin/sh

            # This is the first script called by init process

            /bin/mount  -a

            mdev –s     //挂载dev下所有节点文件

            为rcS添加可执行权限:

            $ chmod   +x  init.d/rcS

 

        10.4、etc下添加profile文件,文件内容为:

            #!/bin/sh

            export HOSTNAME=farsight

            export USER=root

            export HOME=root

            export PS1="[$USER@$HOSTNAME \W]\# "

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

            LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH

            export PATH  LD_LIBRARY_PATH

    11、设备文件创建

        根文件系统中有一个设备节点是必须的,在dev下创建console节点

        $ mknod   dev/console    1

        重要:若新制作的文件系统尺寸若超出8M,则需删除不需要的库文件。

    12、NFS测试

        12.1、备份/source/rootfs

            sudo  mv  /source/rootfs  /source/rootfs_bak

        12.2、将我们新建文件系统拷贝到/source目录下

            sudo  cp  _install   /source/rootfs   –a

        12.3、设置uboot环境变量

            # setenv  bootcmd  tftp  20008000  zImage\; go  20008000

            # setenv  bootargs  root=nfs  nfsroot=192.168.1.100:/source/rootfs  init=/linuxrc console=ttySAC0,115200  ip=192.168.1.200

            # saveenv

    13、重新启动开发板,查看是否能够正常挂载,功能是否正常
    14、制作cramfs文件系统

        14.1cramfs文件系统镜像制作

        由于系统提供制作cramfs文件系统的工具,可以直接使用。具体操作如下;

            $ mkfs.cramfs  /source/rootfs  rootfs.cramfs

        14.2、将rootfs.cramfs拷贝到/tftpboot目录下

            $ sudo  cp  rootfs.cramfs  /tftpboot

        14.3、将rootfs.cramfs烧写到nand flash的第三个分区上

            u-boot下执行如下命令

            # tftp  20008000  rootfs.cramfs

            # nand  erase  400000  400000

            # nand  write  20008000  400000  400000

        14.4、重新设置u-boot启动参数

            # setenv  bootcmd  tftp  20008000  zImage\; go  20008000

            # setenv  bootargs  root=/dev/mtdblock2   init=/linuxrc  console=ttySAC0,115200

            # saveenv

        14.5、启动开发板,测试是否成功。

            [root@farsight /root] # ls /

            bin       etc      linuxrc     sbin     tmp      var

            dev      lib      mnt      proc     test     usr

            [root@farsight /root] # mkdir test

            mkdir: Cannot create directory `test': Read-only file system

        注意:cramfs格式的文件系统是只读的此同时
        另外还可以制作:
制作 jffs2 文件系统与
ramdisk 文件系统。


你可能感兴趣的:(嵌入式软件开发培训笔记——嵌入式linux内核与文件系统移植与分析)