Porting:linux内核编译、配置、修改配置文件、添加.c文件到内核

原创 2017年02月23日 22:47:30
1、linux内核
     www.kernel.org
     $:'uname -a
     $:'uanme -r
     // 查看linux内核版本,开发板上进入linux后是同样的命令。
     早起经常使用的版本:linux 2.6.x
     开发板上使用的版本:linux 3.4.39
     linux最新版本:linux 4.x

2、linux内核的5大功能
     1)内存管理功能;
     2)进程管理及进程间通信;
     3)虚拟文件子系统;
     4)设备驱动管理;
     5)网络子系统;

     嵌入式平台有操作系统,优势在于:
        1)编程简单,有库函数可以调用;
        2)可以实现更加复杂的业务逻辑;// 多进程 多线程

3、linux内核的编译
     env/kernel.tar.bz2
     $:'cp /mnt/hgfs/porting/env/kernel.tar.bz2 .
     $:' tar xvf *.bz2
     $:' cd kernel/
     $:'find ./ -type f | wc -l
     // 26129
     $:'cp arch/arm/configs/x6818_defconfig .config
     $:'vi Makefile
     // 195 ARCH ?= arm
     // 196 CROSS_COMPILE ?= arm-cortex_a9-linux-gnueabi-

     $:'make uImage -j4
     // arch/arm/boot/uImage  is  ready

     $:'make menuconfig -j4
     // 此项为内核功能配置,可删减(内核裁剪)

** 编译异常问题解决 **
     问题1:
     >>如果出现"mkuimage"command not find
     解决办法:
         $:'sudo cp ~/project/uboot/tools/mkimage /usr/bin/
         $:'make uImage
     问题2:
     >>Your display is too small...
     解决办法:
       缩小字体显示比例。

验证uImage的有效性:
    把uImage烧写0x800扇区开始的分区位置。
    通过加载的方式:
    cp arch/arm/boot/uImage /tftpboot/
    tftp 48000000 uImage
    bootm 48000000

    setenv bootcmd tftp 48000000 uImage \; bootm 48000000



3.1 内核的配置
【什么是配置?】
    假设linux内核中提供了10000种功能,但是具体到开发板上只需要其中2000个功能。
    1)裁剪掉内核中不需要的功能
         不需要挂载U盘
         // 内核中关于FAT32类型文件系统相关的代码的支持就不需要
    2)驱动程序的裁剪
         // 产品中没有键盘,裁剪掉内核中的键盘驱动
    【总之】根据目标产品的需要,以及开发板的实际硬件,裁剪掉不需要的内核代码。
【如何完成配置?】
    找一个相近的配置文件,在此基础上进行修改。
【去哪里找相近的配置?】
    1)去内核源码目录  arch/arm/configs/xxx_defconfig
    2)上游厂家提供
【如何修改配置?】
    cp 相近的配置.config  kernel/.config
    a)$:'  make menuconfig
       // 模拟菜单显示界面
         General setup  --->
         System Type  --->
                ARM system type (SLsiAP S5P6818)  --->
         Boot options  --->
         Device Drivers  ---> // 硬件驱动设备
         File systems  ---> // 文件系统
     b)$:' make config
    // 纯文字提示,基本不用
     c)$:'  make xconfig
     // 真实图形显示菜单界面,基本不用
     "make help" 查看内核make帮助命令。

内核本质也是一个裸板程序。
    .o ... .o  ---> elf 文件 (vmlinux)
    vmlinux  ---> Image(.bin)  --->  zImage  ---> uImage
    zImage:解压缩代码 + 压缩后的Image数据
    uImage:64Bytes + zImage
    // 64Bytes:内核的加载地址、内核版本 ... 一般给uboot使用。
    $:'du -h arch/arm/boot/Image
    // 11M
    $:'du -h arch/arm/boot/zImage
    // 5.2M <-b> 5400688,压缩后的Image
    $:' du -harch/arm/boot/uImage
    // 5.2M <-b> 5400752

<tips>
$:'du -h
// 以兆(M)显示文件大小 和 文件名
$:'du -b
// 以字节数显示文件大小 和 文件名

3.2 linux内核的启动过程
     阅读代码,组织工程。
     linux : vim + ctags
     $:'rm arch/arm/mach-s5p6818/prototype/prototype
     $:'ctags -R *
     windows : source insight
     入口点文件:
            $:'rm vmlinux
            $:'make uImage V=1
            // V=1 显示详细的编译过程
            $:'vi arch/arm/kernel/vmlinux.lds
            .head.text : {
                _text = .;
                *(.head.text)
            }
      // 整个linux内核的入口点文件:arch/arm/kernel/head.S
      head.S:
            设置SVC模式
            __lookup_processor_type  // 检查CPU的ID看内核的状态
            bl  __create_page_tables  // 创建页表
            ldr     r13, =__mmap_switched 
            b       __enable_mmu
                 。。。
                 。。。
              b       __turn_mmu_on
              450 ENTRY(__turn_mmu_on)
              457         mov     r3, r13
 458         mov     pc, r3 //跳转到__mmap_switched
__mmap_switched:
b       start_kernel
start_kernel
   -->rest_init
      {
           //创建一个新的内核线程
           kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
      }
         kernel_init( )
          {
             prepare_namespace( )
              {
                 //根据bootargs的参数,挂载根文件系统
                 mount_root( );
              }
              init_post( )
              {
                  //执行用户空间的1号进程
                  run_init_process("/sbin/init");
              }
          }
系统上电--->uboot完成硬件的初始化--->执行bootcmd中的命令--->加载操作系统到内存--->传递参数给内核,并启动内核--->检查CPU ID当前内核是否支持--->创建页表开启MMU--->start_kernel--->创建一个新的内核线程--->根据参数去挂载根文件系统--->从根文件系统中找到1号进程--->创建执行1号进程--->1号进程后续会创建子进程/bin/bash--->用户可以输入命令

    移植内核的关键文件:arch\arm\mach-s5p6818\cpu.c
    其中的关键代码信息:
            static void __initcpu_init_machine ( void ) {
                ...
            nxp_cpu_devs_register ( );
           nxp_board_devs_register ( );
            }
           // 该函数是在 kernel_init 中被调用,即系统启动过程中被调用。
            kernel_init ( ) {
                do_basic_setup ( ) {
                    do_initcalls ( ) {
                        ...
                       cpu_init_machine ( ); // 移植的重点。要改的函数。
                    }
                }
            }

4、配置过程是如何影响编译过程的
$:'  make menuconfig
    Device Drivers  --->
            Character devices  ---> 
                     -*- LED Support  ---> 
                    // LED Support for GPIO connected LEDs ---> help
---> 变量:CONFIG_LEDS_GPIO
$:' vi .config
CONFIG_LEDS_GPIO=y     // <*>
CONFIG_LEDS_GPIO=m   // <M>
# CONFIG_LEDS_GPIO is not set   // < >

【结论1】配置的结果是以变量取不同的值的形式保存在 .config 文件中。
【结论2】内核中几乎所有的目录下都有Makefile文件。
【结论3】各个子目录下的Makefile决定了当前目录下的文件(夹)是否参与编译过程。
$:'grep "CONFIG_LEDS_GPIO" * -nRw
   // grep显示行号-递归-内容检索:
    drivers/leds/Makefile:22行使用了该变量
    obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
    <*>   CONFIG_LEDS_GPIO=y  ' boj-y += leds-gpio.o
    <M> CONFIG_LEDS_GPIO=y  ' boj-m += leds-gpio.o    
    < >   CONFIG_LEDS_GPIO=y  ' boj-  += leds-gpio.o
【结论4】
在编译内核时 boj-y += xxx.o 代表 xxx.c 参与编译,并最终链接到内核uImage;
在编译内核时 boj-m += xxx.o 代表 xxx.c 参与编译,但不会链接进内核uImage,生成一个独立的xxx.o;
在编译内核时 boj-  += xxx.o 代表 xxx.c 不参与编译。


5、如何将一个.c文件编译进内核
// env/led_drv.c
$:'cp /mnt/hgfs/porting/env/led_drv.c drivers/char/
$:'vi drivers/char/Makefile
增加1行:obj-y               += led_drv.o
$:'make uImage
$:' cp arch/arm/boot/uImage  /tftpboot/

#:' tftp 48000000 uImage
#:' bootm 48000000
#:'dmesg >1.txt
#:'dmesg | grep "led_init"
版权声明:本文为博主<布衣不才>原创文章,未经允许不得转载。 || 博客地址:blog.csdn.net/sinat_36184075

Linux内核配置和编译过程详解

一、引言:  本文档的内容大部份内容都是从网上收集而来,然后配合一些新的截 图(内核版本:V2.4.19)。在每一配置项后会有一个选择指南的部份,用来指导大家怎么样 根据自己的情况来做相应的选择;还...

Linux内核的Makefile和kconfig解读,如何在内核中添加自己的代码

一、概述    在内核编译中如何将各个目录树中的文件组织起来编译是一个很重要的问题,并且要根据用户配置来编译特有的内核。为了解决这个问题,内核使用两种文 件,Makefie和Kconfig。分布到各...

Linux内核中读写文件数据的方法

Linux内核中读写文件数据的方法     有时候需要在Linuxkernel--大多是在需要调试的驱动程序--中读写文件数据。在kernel中操作文件没有标准库可用,需要利用kernel的一些...

LINUX C 配置文件的读,添加,修改,删除

/* *从配置文件中读取相应的值 *输入参数:1,配置文件路径 2,匹配标记 3,输出存储空间 *并且排除了空行,“=”前后无内容,无“=”的情况 */ReadConfig(char *conf_pa...

Linux下配置文件读取操作流程及其C代码实现

一、概述 Linux具有免费、可靠、安全、稳定、多平台等特点,因此深受广大程序员的欢迎。 为了体现软件产品的灵活性,可添加配置文件存放某些重要的参数,在部署的时候根据实际的安装环境对每个配置项的值...
  • zhouzxi
  • zhouzxi
  • 2015年05月07日 16:47
  • 10260

linux C 修改配置文件

修改配置文件,当时是用作ftp的动态修改接口函数的修改 代码如下: #include #include #include #define DEFAULT_PATH "/home/vsftpd...

LINUX C 读写修改删除配置文件函数

原文地址:http://blog.csdn.net/mochouxiyan/archive/2008/09/14/2913825.aspx *从配置文件中读取相应的值 *输入参数:1,配置文件路...

linux常用环境变量和c/c++头文件/库路径环境变量

环境变量设置 /etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行。并从/etc/profile.d目录的...

實作 Layer 7 封包過濾

转贴自 : http://ms.ntcb.edu.tw/~steven/article/kernel-layer7-filter.htm 實作 Layer 7 封包過濾 ...

Spring Security3源码分析(17)-Filter链排序分析

通过前面Spring Security提供的各种Filter的分析,大体上知道每个Filter具体的用途了。  Spring Security一共提供了20个Filter,我目前只分析了13个(如果...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Porting:linux内核编译、配置、修改配置文件、添加.c文件到内核
举报原因:
原因补充:

(最多只允许输入30个字)