linux源码树结构


参考 http://www.360doc.com/content/13/0410/17/7044580_277403053.shtml

目录 描述
arch 目录包括了所有和体系结构相关的核心代码。它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CPU及与之相兼容体系结构的子目录。PC机一般都基于此目录。
block 块设备I/O层
crypto 加密API
documentation 目录下是一些文档,是对每个目录作用的具体说明。
drivers 目录中是系统中所有的设备驱动程序。它又进一步划分成几类设备驱动,每一种有对应的子目录
firmware 使用某些驱动程序而需要的设备固件
fs VFS和各种文件系统,存放Linux支持的文件系统代码。不同的文件系统有不同的子目录对应,如ext3文件系统对应的就是ext3子目录。
include 目录包括编译核心所需要的大部分头文件,例如与平台无关的头文件在include/linux子目录下。
init 目录包含核心的初始化代码(不是系统的引导代码),有main.c和Version.c两个文件。这是研究核心如何工作的好起点。
ipc 核心进程间的通信代码
kernel 内核管理的核心代码放在这里。同时与处理器结构相关代码都放在arch/*/kernel目录下
lib 通用的核心库的代码,不过与处理器结构相关的库代码被放在arch/*/lib/目录下
mm 内存管理子系统和VM。与具体硬件体系结构相关的内存管理代码位于arch/*/mm目录下。
net 目录里是核心的网络部分代码,其每个子目录对应于网络的一个方面。
samples 示例,示范代码
scripts 配置和编译内核所用的脚本文件
security linux安全模块
sound 语音子系统
usr 早期的用户空间代码,所谓的initramfs
tools 在linux开发中有用的工具
virt 虚拟化基础结构

获取源码包的方式


为什么要活取源码包?


在笔者到官网下载源码时,源码下面有如下说明:

If you are simply trying to build third-party modules for your kernel, you do not want this package. Install the appropriate linux-headers package instead. 意思是,如果你只是想为内核编译第三方的模块,那么,你不需下载此源码包。安装内核头文件包或
许会更适合你。

如果你的ubuntu是保持更新的(比如您经常执行sudo apt-get update和dist-upgrade),
那么您的系统是安装有内核头文件包的,不信您到/usr/src目录下查看,是不是有linux-headers-[版本号]-generic的文件夹呢,呵呵。我现在可以说,你可以在此开发你的驱动程序了。

但是为什么我们还要活取源码呢?
前面已经提到如果你只是想为内核编译第三方的模块,那么,你不需下载此源码包。安装内核头文件包或许会更适合你。
但是很多时候我们做嵌入式开发或者驱动开发,一个基本的Linux设备驱动开发环境由宿主机目标机组成,宿主机就是用来做驱动开发工作的主机,目标机就是用来运行和测试设备驱动的主机,在宿 主机上需要有开发工具(gcc,gdb,make等)和linux源码(版本要对应目标机上的linux内核),而目标机上只要运行linux即可。由于 步骤有所不同,下面分为普通Linux设备驱动开发嵌入式Linux设备驱动开发两种情况来讲述环境的搭建和驱动程序的编译:

普通Linux设备驱动开发


普通Linux主要是区别于于嵌入式Linux(一般指uClinux),在这种开发中宿主机和目标机可以是一台主机
即在本机上开发编译然后在本机 上加载运行(Linux设备驱动也可以直接编译进内核,但为了开发工作方便,一般采用动态加载的方式),
当然也可以是两台主机
如果是两台主机的话,要保证宿主机上的linux源码的版本号与目标机中的linux内核版本一致。
普通Linux设备驱动开发的步骤如下:
①在宿主机上安装开发工具和下载linux源码(要求版本号和目标机上的linux内核版本一致)。开发工具主要有gcc、gdb、make等,
②编写Linux驱动程序
是需要修改内核源代码的。那么这就需要我们在本地主机上安装一份源码,在编译成库后,在进行驱动开发。
③编写Makefile文件
④编译出驱动文件
加载并测试以及卸载:加载使用insmod或modprobe命令来实现,使用rmmod命令卸载驱动模块

嵌入式Linux设备驱动开发


这种开发中一般目标机为带有嵌入式处理器的开发板,而宿主机为PC,开发环境需要在宿主机上搭建,嵌入式Linux设备驱动开发的步骤如下:
①在宿主机上下载嵌入式Linux的源码,并安装嵌入式Linux开发工具(针对于不同的嵌入式处理器,工具也有所不同,如对应于Arm的arm-gcc系列,针对nios2处理器的nios2-cc系列)
②编写Linux设备驱动驱动程序,将该文件复制到(linux 源码目录)/drivers/(目标文件夹)/中
③配置以及修改内核源码的信息以及makefile文件,在此步配置中可以选择将我们编写的驱动编译进内核还是不选择编译,但是不能选择编译成模块
④配置并且编译内核
⑤将内核烧写在开发版上进行测试:将生成的zImage文件下载到开发板,开发板上的嵌入式Linux启动后可以用insmod或modprobe加载驱动模块,测试完毕后可以通过rmmod命令卸载驱动模块

总结


因此在开发驱动的时候如果你只是想为内核编译第三方的模块,那么,你不需下载此源码包。安装内核头文件包或许会更适合我们,但是多数情况下,我们可能时需要修改内核源代码信息的,这就需要我们在宿主机维护一份与目标机上相同的内核信息,否则我们怎么保证我们编写的驱动可以在目标机器上运行呢。。。。

源码包活取的方法


linux源码可以通过以下几种途径获得:
直接去www.kernel.org下载
https://www.kernel.org/pub/linux/kernel/

通过包管理工具下载源码,在debian和Ubuntu中可以通过下面这个命令下载,apt-get install linux-source-(版本号) ,下载后的文件在/usr/src目录中,解压到该目录即可

获取源码包


注意:
如果您只是为了简单的学习下驱动的开发,而不期望深层次的探究Linux内核的机制,那么您完全可以跳过此步骤,单使用头文件您是完全可以进行简单的第三方驱动开发的。

直接从内核官网上下载


使用发行版自带的源码包


Ubunto14.04


安装编译内核所需要的软件build-essential、autoconf、automake、cvs、subversion

sudo apt-get install build-essential kernel-package libncurses5-dev 

注意:libncurses5这个软件包在使用menuconfig配置内核的时候会用到。

ls一下/usr/src首先看下我们的系统中有没有源码包,仅仅有内核头文件包

进入/usr/src ,在这里构建源码树,我们用下面指令查看可用的源码包

sudo apt-cache search linux-source 


可以看到得到如下信息

linux-source - Linux kernel source with Ubuntu patches
linux-source-3.13.0 - Linux kernel source for version 3.13.0 with Ubuntu patches

那么就让我们来下载3.13.0版的kernel,通过使用命令下载内核

sudo apt-get install linux-source-3.13.0

下载完成后,会自动的存放在/usr/src下,

在/usr/src/下ls以下

解压缩源码包

sudo tar jxvf  linux-source-3.13.0.tar.bz2

这样我们就已经获取到了一份完整的源码包,

CentOS构建源码树


获取内核头文件


构建的之前,最好先

yum update

把内核升级到最新版本。至于具体安装哪一份源码树,要看你用的哪一种内核,用uname -a可以看到。

先检查看看有哪些源码包

yum list | grep kernel

如果用的普通内核,就

yum install kernel-headers kernel-devel

如果用的PAE内核,就

yum install kernel-headers kernel-PAE-devel

如果用的xen内核,就

yum install kernel-headers kernel-xen-devel

centos安装内核源代码


但是上面的方式只会为我们安装内核的头文件目录以及库信息,如果我们期望获取到源码需要下面的操作

参照

I Need to Build a Custom Kernel

I Need the Kernel Source

下面我们的方式是使用构建本地组内搭建内部yum源的方式安装linux内核的源码包

目前我们实验室的服务器系统是centos5.11,地址 http://vault.centos.org/5.11/os/SRPMS/kernel-2.6.18-398.el5.src.rpm
不同的版本,下载地址更改一下即可
其他下载地址http://rpm.pbone.net/index.php3

  • 1.安装 rpmbuild
    rpmbuild是用来制作rpm包的工具
yum install rpm-build redhat-rpm-config unifdef 
  • 2.下载源码包
wget http://vault.centos.org/5.11/os/SRPMS/kernel-2.6.18-398.el5.src.rpm

  • 3.安装内核源码
rpm -ivh kernel-2.6.18-274.el5.src.rpm 

这样我们的源码就已经下载好了,在/usr/src/redhat目录下有我们需要的所有东西。
但是到现在我们只是安装了环境目录,以及源码的压缩包,但是并没有安装

我们可以看到我们已经有了源码的压缩包,但是并没有解压缩,因此我们下面执行的操作其实就是用工具对其进行解压缩。
* 4.安装源码包

cd  /usr/src/redhat/SPECS
rpmbuild -bp --target=`uname -m` kernel.spec 2> prep-err.log | tee prep-out.log

以上步骤完成以后,查看prep-err.log错误日志,
如果没有错误,则成功解出的内核源码位置在 /usr/src/redhat/BUILD 目录下

编译内核


按原来的kernel配置,配置kernel.

sudo make oldconfig

make(相当耗时),开始编译内核

sudo make

编译内核镜像

sudo make bzImage

安装内核模块

make modules_install

执行结束之后,会在/lib/modules下生成新的目录/lib/modules/3.13.0-48-generic/, 下面的build文件就是编译模块的要用到的文件。至此内核编译完成。

卸载无用的内核相关文件


我们为不同的目标机配置不同的内核模块,这样一段时间后,我们的系统中会有多份内核信息,再加上我们的系统由于自动升级,系统里也会安装了很多内核。这样始终用不到的旧内核或者无用内核有必要清理一下,以节省启动时间和硬盘空间。


然后通过查看本机上所有内核的列表来决定哪些需要删除掉:

运行命令:

dpkg --get-selections|grep linux

例如我本机显示为:

注意:
不要删除当前使用的版本.后面的install表示已安装,deinstall表示曾经安装过,现在已被删除(已不占空间).
首先可查看当前用的内核是哪个,可通过命令:uname -a 来获得信息。

其中带有image的就是内核文件,因此可看出我的机器上共五个内核镜像版本。但是其实只安装了2个镜像,这个卸载的时候我们就会发现,我当前使用的是3.13.0-49,所以决定将其它没用的内核删除。
删除内核镜像的命令

删除的命令为:sudo apt-get remove linux-image-XXXX

例如我要卸载3.13.0-48的旧内核镜像,那么运行命令

sudo apt-get purge linux-image-3.13.0-48-generic

或者

sudo apt-get remove linux-image-3.13.0-48-generic


我们会发现linux-image-extra-3.13.0-48-generic也会跟着被卸载,
这时候我们ls /lib/modules/3.13.0-48-generic/会发现,安装的内核镜像文件已经没有了

卸载内核头文件

sudo apt-get purge linux-headers-3.13.0-48

或者

sudo apt-get remove linux-headers-3.13.0-48


这条命令会自动把linux-headers-3.13.0-48-generic删除,如果未删除我们同样可以使用命令删除即可。
最后再次运行命令,查看安装的内核文件,查看是否卸载成功

dpkg --get-selections|grep linux

最后最好刷新一个启动菜单

sudo update-grub

Linux内核剖析(三)构建源码树的更多相关文章

  1. Linux内核剖析(四)为arm内核构建源码树

    前面说到要做linux底层开发或者编写Linux的驱动,必须建立内核源码树,之前我们提到过在本机上构建源码树—-Linux内核剖析(三),其建立的源码树是针对i686平台的,但是我么嵌入式系统用的是a ...

  2. Linux内核剖析(五)Linux内核的构建过程

    参考 一次实验引发的故事 – kernel build system探索—vmlinux是如何炼成的– kernel makefile 深度探索Linux操作系统:系统构建和原理解析.pdf 问题 在 ...

  3. 【转帖】Linux的历史----Linux内核剖析(一)

    Linux的历史----Linux内核剖析(一) 2015年04月09日 10:51:09 JeanCheng 阅读数:11351更多 所属专栏: Linux内核剖析    版权声明:本文为博主原创文 ...

  4. [转帖]Linux内核剖析(一)Linux的历史

    Linux内核剖析(一)Linux的历史 https://www.cnblogs.com/alantu2018/p/8991158.html Unix操作系统 Unix的由来 汤普逊和里奇最早是在贝尔 ...

  5. Linux内核的三种调度策略

    一 Linux内核的三种调度策略:   1,SCHED_OTHER 分时调度策略, 2,SCHED_FIFO实时调度策略,先到先服务.一旦占用cpu则一直运行.一直运行直到有更高优先级任务到达或自己放 ...

  6. linux内核的三种主要调度策略

    linux内核的三种主要调度策略: 1,SCHED_OTHER 分时调度策略, 2,SCHED_FIFO实时调度策略,先到先服务 3,SCHED_RR实时调度策略,时间片轮转 实时进程将得到优先调用, ...

  7. 嵌入式Linux内核+根文件系统构建工具-Buildroot 快速入手指导【转】

    本文转载自:https://my.oschina.net/freeblues/blog/596448 嵌入式Linux内核+根文件系统构建工具-Buildroot 快速入手指导 buildroot 是 ...

  8. 【转载】你知道 Linux 内核是如何构建的吗?

    内核的根 Makefile 负责构建两个主要的文件:vmlinux (内核镜像可执行文件)和模块文件.内核的 Makefile 从定义如下变量开始: VERSION = PATCHLEVEL = SU ...

  9. Linux内核剖析(一)Linux的历史

    Unix操作系统 Unix的由来 汤普逊和里奇最早是在贝尔实验室开发Unix的,此后的10年,Unix在学术机构和大型企业中得到了广泛的应用,当时的UNIX拥有者AT&T公司以低廉甚至免费的许 ...

随机推荐

  1. 【LeetCode算法-7】Reverse Integer

    LeetCode第7题: Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 123 Outp ...

  2. HDU 5672 String 【尺取】

    <题目链接> 题目大意:给定一个只由26个小写字母组成的字符串,现在问你至少包含k个不同字母的连续子序列总数有多少. 解题分析:经仔细研究,我们发现,每次尺取到符合要求的最小区间,然后将区 ...

  3. CodeForces 371C Hamburgers(经典)【二分答案】

    <题目链接> 题目大意: 给以一段字符串,其中只包含"BSC"这三个字符,现在有一定量免费的'B','S','C‘,然后如果想再买这三个字符,就要付出相应的价格.现在总 ...

  4. 001.Kubernetes简介

    一 Kubernetes概述 Kubernetes是一个全新的基于容器技术的分布式架构领先方案.Kubernetes(k8s)是Google开源的容器集群管理系统(谷歌内部:Borg).在Docker ...

  5. Javascript你必须要知道的面试题

    1.使用 typeof bar === "object" 判断 bar 是不是一个对象有神马潜在的弊端?如何避免这种弊端? 使用 typeof 的弊端是显而易见的(这种弊端同使用 ...

  6. BZOJ.2115.[WC2011]Xor(线性基)

    题目链接 \(Description\) 给定一张无向带边权图(存在自环和重边).求一条1->n的路径,使得路径经过边的权值的Xor和最大.可重复经过点/边,且边权和计算多次. \(Soluti ...

  7. Python应用【PDF处理-pypdf2】

    概述 Python处理PDF文件需要安装相应的库:[PyPDF2]库 使用场景 工作中可能会涉及处理pdf文件,PyPDF2就是这样一个库, 使用它可以轻松的处理 pdf 文件,它提供了读.写.分割. ...

  8. curl获取结果乱码的解决方法之CURLOPT_ENCODING(curl/Post请求)

    //php脚本开始   /*POST请求远程内容函数*/   function ppost($url,$data,$ref){ // 模拟提交数据函数       $curl = curl_init( ...

  9. 潭州课堂25班:Ph201805201 django框架 第四课 模板常用标签,模板继承与引用,自定义过渡器 (课堂笔记)

    if 语句 判断传入的 name 值 建好这些文件后,对 url 进行配置 在浏览器中访问 for 循环 页面跳转: 通过  name 跳转时要在 urls 文件中为该 path 设置 name 带参 ...

  10. 面试题fugui02

    一.概念题 1.描述对super.pass.yield.lambda关键字修饰的理解 2.大致描述一下python GIL的机制,以及python中多线程和多进程的区别 GIL全局解释器锁,是pyth ...