LINUX内核配置与编译

移植LINUX内核,就是为了让LINUX系统在自己的硬件平台上运行起来,能正常工作。其中最重要的还是驱动的移植,只有驱动程序能驱动硬件设备,上层的应用程序才能正常运行。

目前,LINUX支持内核的系列主要有以下,解压linux-3.5-20131028.tgz文件,进入到文件夹里面,

除了arch文件夹里面,都是大多数平台相同的文件:

在kernel文件夹里面,包含着一些内核的文件;

在arch文件里面是支持的各种平台文件,里面是一些芯片公司支持的一些驱动程序;

一般来说,LINUX系统剪裁都分为以下几步:

第一步:解压   linux-3.5-20131028.tgz  linux源码包,进入linux-3.5文件夹,

第二步:配置 .config文件,这里,直接使用的是   tiny4412_linux_defconfig  

                    cp  tiny4412_linux_defconfig  .config

第三步:选择生成模块,这一步,可以选择需要那些模块编译进镜像文件,因为,考虑到各种功耗的问题,有些linux模块的      功 能是没有必要编进内核

      make menuconfig  进入选择模块编译

第四步:make 生成   zImage  镜像,这个就类似于装windos系统的.iso文件之类的。之前,在配置交叉编译环境的时候就是用的这个文件镜像。

第五步:dnw到板子,把板子的linux系统跑起来,到这里,linux系统是在板子上成功运行:

接下来,是内核模块的编写部分:

    先贴代码:

1 #include <linux/init.h>
  2 #include <linux/module.h>
  3 
  4 MODULE_LICENSE("GPL");
  5 MODULE_AUTHOR("bunfly");
  6 
  7 int test_init()
  8 {
  9     printk("hahahhahahahah
");
 10 
 11     return 0;
 12 }
 13 
 14 void test_exit()
 15 {
 16     printk("exit
");
 17 }
 18 
 19 module_init(test_init);
 20 module_exit(test_exit);
 21 

因为是在内核层,所以没有以前的include<stdio.h>之类的头文件,这里换成了两个linux/init。和linux/module头文件

7 int test_init()
  8 {
  9     printk("hahahhahahahah ");
 10
 11     return 0;
 12 }

在这里写了一个函数,打印一句话,

而在 19 module_init(test_init)行,这里用了一个回调函数来调用test.init函数,这个回调函数是加载到内核的时候,执行的函数;

那么,module_exit(); 就是从内核卸载时执行的函数;

4 MODULE_LICENSE("GPL");///声明开发模块遵循的的开源协议
5 MODULE_AUTHOR("bunfly"); //申明模块的开发者
这两行在如果不申明的话将会出现警告:

  1 
  2 ha:
  3     make -C /home/bunfly/source_code/linux-3.5 M=/home/kernel/arm/ram/520/1st
  4 
  5 clean:
  6     make -C /home/bunfly/source_code/linux-3.5 M=/home/kernel/arm/ram/520/1st cle    an
  7 
  8 
  9 obj-m += test.o
 10 

 以上是makefile文件

   make生成.ko文件, 在板子上加载到内核模块:

接下来的一个程序,打印出任务的名字:

  2 #include <linux/thread_info.h>
  3 #include <linux/module.h>
  4 #include <linux/sched.h>
  5 
  6 MODULE_LICENSE("GPL");
  7 MODULE_AUTHOR("bunfly");
  8 
  9 int test_init()
 10 {
 11     int i = 0;
 12     struct task_struct *t;
 13     struct thread_info *info;//线程信息
 14 
 15     unsigned long addr = (unsigned long)&i;
 16     unsigned long base = addr & ~0x1fff;//以8K的字节对齐
 17     info = (struct thread_info *)base;//找到线程的地址
 18     t = info->task;//获得任务信息
 19     printk("%s
", t->comm);//打印出任务的名字
 20 
 21     return 0;
 22 }
 23 
 24 void test_exit()
 25 {
 26     printk("exit
");
 27 }
 28 
 29 module_init(test_init);
 30 module_exit(test_exit);
 31

makefile:

  1 
  2 ha:
  3     make -C /home/bunfly/source_code/linux-3.5 M=`pwd`
  4 
  5 clean:
  6     make -C /home/bunfly/source_code/linux-3.5 M=`pwd` clean
  7 
  8 obj-m += test.o
  9 
~                                                                                                 
~   

    make 

    在ARM板子上运行:

  

  总结:本次通过自己适当剪裁,生成一个在zImage镜像文件,而且,自己写了一个简单的内核模块,在ARM板子上,插入内核模块,运行。

  在这里,有些固定的方式:例如,内核代码的Makefile文件,以后需要编译内核模块都是固定的方法:

而在第二个文件中的,通过使用以对齐的方式找到地址;获得固定结构体task里的名字参数comm的做法,应该深入理解,并且灵活运用:

   补充一下建立索引来搜索文件里的小知识,对于查找文件关键字很有用  ctags

    首先到需要搜索的目录下面:建立索引文件:ctags   -R .   ..

                  随便打开任意文件:vim hong

                  查找关键字:ta   xxxx

                  如果要继续查找某一关键字,只需要将光标移动到上面按下:ctrl+ ]

                  返回刚才查找的结果       ctrl  +   o

    

      

下面是LINUX内核开发的工作流程

原文地址:https://www.cnblogs.com/hongzhunzhun/p/4517890.html