手把手带你实现Linux内核编译步骤及配置

2023-11-15

linux 系统体系结构:

linux kernel体系结构:
arm有7种工作模式,x86也实现了4个不同级别RING0-RING3,RING0级别最高,
这样linux用户代码运行在RING3下,内核运行在RING0,这样系统本身就得到了
充分的保护

用户空间(用户模式)转到内核空间(系统模式)方法:
·系统调用
·硬件中断

linux kernel 体系结构:

虚拟文件系统VFS:

VFS(虚拟文件系统)隐藏各种文件系统的具体细节,为文件操作提供统一的接口

二.Linux内核源代码

linux内核下载http://www.kernel.org

目录结构:

解压linux kernel tar后目录

·arch:根据cpu体系结构不同而分的代码

·block:部分块设备驱动程序

·crypto:加密,压缩,CRC校验算法

·documentation:内核文档

·drivers:设备驱动程序

·fs(虚拟文件系统vfs):文件系统

·include:内核所需的头文件,(与平台无关的头文件在include/linux中)

·lib:库文件代码(与平台相关的)

·mm:实现内存管理,与硬件体系结构无关的(与硬件体系结构相关的在arch中)

·net:网络协议的代码

·samples:一些内核编程的范例

·scripts:配置内核的脚本

·security:SElinux的模块

·sound:音频设备的驱动程序

·usr:cpio命令实现,用于制作根文件系统的命令(文件系统与内核放到一块的命令)

·virt:内核虚拟机

linux DOC 编译生成:

linux源根目录/Documentation/00-INDEX:目录索引
linux源根目录/Documentation/HOWTO:指南
·生成linux内核帮助文档:在linux源根目录(Documentation) 执行make htmldocs

ubuntu16下需要执行sudo apt-get install xmlto安装插件才可生成doc文档

后面开发中经常要改的是arch,drivers中的代码

三.Linux内核配置与编译

清理文件(在linux源码根目录):

·make clean:只清理所有产生的文件

·make mrproper:清理所有产生的文件与config配置文件

·make distclean:清理所有产生的文件与config配置文件,并且编辑过的与补丁文件

配置(收集硬件信息如cpu型号,网卡等...):

·make config:基于文本模式的交互配置

·make menuconfig:基于文本模式的菜单模式(推荐使用)

·make oldconfig:使用已有的.config,但会询问新增的配置项

·make xconfig:图形化的配置(需要安装图形化系统)

配置方法:

1)使用make menuconfig操作方法:

1>按y:编译>连接>镜像文件

2>按m:编译

3>按n:什么都不做

4>按"空格键":y,n轮换

配置完并保存后会在linux源码根目录下生成一个.config文件

注意:在ubuntu11上要执行apt-get install libncurses5-dev来安装支持包

2)利用已有的配置文件模板(.config)

1>linux源码根目录/arch/<cpu架构>/configs/<具体某一的CPU文件>,把里面对应的文件copy并改名为.config至linux源码根目录下

2>利用当前运行已有的文件(要用ls /boot/ -a查看)把/boot/config-2.6.18-53.e15拷贝并改名为.config至linux源码根目录下执行以上操作就可以用make menuconfig在拷贝

.config文件上面修改文件了

编译内核:

1)make zImage

2)make bzImage

区别:在X86平台上,zimage只能用于小于512k的内核

获取详细编译信息:make zimage V=1 或 make bzimage V=1

编译好的内核在:arch/<cpu>/boot/目录下

注意:在把.config配置文件cp到根目录编译内核前,必须进入make menuconfig并保存退出(否则生不了效)

编译并安装模块:

1)编译内核模块:make modules

2)安装内核模块:make modules_install INSTALL_MOD_PATH=/lib/modules

更换本机器内核:将编译好的内核模块从内核源码目录copy至/lib/modules下

制作init ramdisk():输入执行命令mkinitrd initrd-2.6.39(任意) 2.6.39(可通过查询/lib/modules下的目录得到)

注意:

mkinitrd命令为redhat里面的,ubuntu的命令为:mkinitramfs -k /lib/modules/模块安装位置 -o initrd-2.6.39(任意) 2.6.39(可通过查询/lib/modules下的目录得到)

如果ubuntu里面没有mkinitramfs命令可以用apt-get install initrd-tools进行安装

安装内核模块:

1)手动

1>cp linux根目录/arch/x86/boot/bzImage /boot/mylinux-2.6.39

2>cp linux根目录/initrd-2.6.39 /boot/initrd-2.6.39

最后修改/etc/grub.conf或/etc/lilo.conf文件

2)自动

1>make install:这个命令会自动完成上面的操作(查看当前内核版本:uname -r)

四.linux内核模块开发

描述:
linux内核组件非常庞大,内核ximage并不包含某组件,而是在该组件需要被使用的时候,动态的添加到正在运行的内核中(也可以卸载),这种机制叫做“内核模块”的机制。内核模块通常通过使用makefile文件对模块进行编译

模块安装与卸载:
1)加载:insmod hello.ko
2)卸载:rmmod hello
3)查看:lsmod
4)加载(自动寻找模块依赖):modprobe hello
modprobe会根据文件/lib/modules/version/modules.dep来查看要加载的模块,看它是否还依赖于其他模块,如果是,会先找到这些模块,把它们先加载到内核

实例分析:
1)moduleDep/1(一个模块的编译)

#include <linux/module.h>
#include <linux/init.h>

//模块入口函数
//__init:表示代码段中的子段,里面的内容只运行一次并且回收内存.
static int __init hello_init(void)
{
    printk(KERN_EMERG "hello world!\n");
    return 0;
}
//模块卸载函数
//__exit:
static void __exit hello_exit(void)
{
    printk(KERN_EMERG "hello exit!\n");
}
//内核符号导出 函数
int add_integar(int a,int b)
{
    return a+b;
}
int sub_integar(int a,int b)
{
    return a-b;
}

module_init(hello_init);
module_exit(hello_exit);
//函数导出
EXPORT_SYMBOL(add_integar);
EXPORT_SYMBOL(sub_integar);

makefile:

#第一次执行KERNELRELEASE是空的,所以执行else里面的
ifneq ($(KERNELRELEASE),)

obj-m :=hello.o

#else块
else

KDIR:= /lib/modules/2.6.18-53.el5/build

all:
#KDIR    依赖内核模块源代码路径(内核编译安装路径)
#PWD     表示内核代码在哪(当前目录)
#modules 编译的是模块
    make -C $(KDIR) M=$(PWD) modules 

clean:
    rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order

endif

2)moduleDep/2(两个模块的编译)

#include <linux/module.h>
#include <linux/init.h>
//模块可选信息
MODULE_LICENSE("GPL");//许可证声明
MODULE_AUTHOR("liyuan");//作者声明
MODULE_DESCRIPTION("This module is a param example.");//模块描述
MODULE_VERSION("V1.0");//模块别名
MODULE_ALIAS("a simple module");//模块别名

//模块参数
static char *name = "liyuan arg";
static int age = 30;
//S_IRUGO是参数权限,也可以用数字
module_param(age,int,S_IRUGO);
module_param(name,charp,S_IRUGO);


//使用外部文件函数
extern int add(int a,int b);


//声明 外部内核符号 函数
extern int add_integar(int a,int b);
extern int sub_integar(int a,int b);

static int __init mains_init(void)
{
     //多文件编译

    printk(KERN_EMERG"param hi");
    int vle=add(1,2);
    printk(KERN_EMERG"add value:%d\n",vle);
    //模块参数

     printk(KERN_EMERG" name : %s\n",name);
     printk(KERN_EMERG" age : %d\n",age);

    //使用其他模块的函数(内核符号导出)
    int adds=add_integar(3,1);
    int subs=sub_integar(3,1);
    printk(KERN_EMERG" add_integar : %d\n",adds);
    printk(KERN_EMERG" sub_integar : %d\n",subs);
    return 0;
}

static void __exit mains_exit(void)
{
    printk("param exit!");
}

module_init(mains_init);
module_exit(mains_exit);

add.c

int add(int a,int b)
{
    return a+b;
}

makefile

ifneq ($(KERNELRELEASE),)
#两个以上内核源文件 生成单独的内核模块名ma

#内核ma
obj-m :=ma.o
#下面的ma-objs前面必须和上面一样为ma
ma-objs := mains.o add.o

else

KDIR:= /lib/modules/2.6.18-53.el5/build

all:
        make -C $(KDIR) M=$(PWD) modules 
clean:
    rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order

endif

运行带参模块:insmod hello.ko name=yuan age=12
内核符号导出(/proc/kallsyms记录了内核中所有导出的符号的名字与地址):
一个内核模块的运行依赖另一个内核模块的函数实现,必须先运行第一个内核模块,这样就需要进行内核符号导出。

注意:
错误信息:disagrees about version of symbol struct_module insmod:error inserting ...
开发内核模块时会出现,内核模块不匹配的情况.是你当前运行的linux内核与编译连接所依赖的
内核版本不匹配,解决方法:
·使用modprobe --force-modversion强行插入
·可使用uname -r进行查看当前运行的内核版本

printk内核打印:
在<linux/kernel.h>中printk有8个优先级,按优先级递减的是:
·KERN_EMERG 0
用于紧急的消息,常常是那些崩溃的消息
·KERN_ALERT 1
需要立刻行动的消息
·KERN_CRIT 2
严重情况
·KERN_ERR 3
错误情况
·KERN_WARNING(printk默认级别) 4
有问题的警告
·KERN_NOTICE 5
正常情况,但是仍然值得注意
·KERN_INFO 6
信息消息
·KERN_DEBUG 7
用作调试消息

不管是哪个级别的都会在/var/log/messages里面打印出来(messages可以删除后,运行内核进行测试内核打印情况)控制台打印(优先级配置/proc/sys/kernel/printk)

总结一下我们的安装步骤:

1、获取内核源码,解压至/usr/src
           # tar xf linux-3.13.5.tar.xz -C /usr/src
           # ln -sv /usr/src/linux-3.13.5  /usr/src/linux
       2、配置内核特性(选择一种方法就可以了)
           make config:遍历选择所要编译的内核特性
           make allyesconfig:配置所有可编译的内核特性
           make allnoconfig:并不是所有的都不编译
           make menuconfig:这种就是打开一个文件窗口选择菜单
           make kconfig(KDE桌面环境下,并且安装了qt开发环境)
           make gconfig(Gnome桌面环境,并且安装gtk开发环境)
       3、编译内核
           # make [-j #] : #号最多为CPU物理核心总数的两倍,这样会快点哦            
       4、安装内核模块
           # make modules_install
       5、安装内核
           # make install
       6、验正并测试
           # cat /boot/grub/grub.conf
           查看新内核是否已经添加, 而后重启系统并测试

原文作者:konglingbin

原文地址:Linux 内核编译步骤及配置详解(版权归原文作者所有,侵权留言联系删除)

内核资料直通车:Linux内核源码技术学习路线+视频教程代码资料

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

手把手带你实现Linux内核编译步骤及配置 的相关文章

  • Web 本地应用程序 Apache:运行 shell 脚本

    我开发了一个 shell 脚本 我想用它创建一个 UI 我决定使用带有本地服务器的 Web 界面 因为我对 HTML PHP 的了解很少 比 QT 或 Java 的了解更多 我只是希望我的 html 可以在我的计算机上运行 shell 脚本
  • 在linux x86平台上学习ARM所需的工具[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有一个 x86 linux 机器 在阅读一些关于 ARM 的各种信息时 我很好奇 现在我想花一些时间学
  • MYSQL插入GB大小的巨大SQL文件

    我正在尝试创建 Wikipedia DB 副本 大约 50GB 但在处理最大的 SQL 文件时遇到问题 我使用 linux split 实用程序将 GB 大小的文件拆分为 300 MB 的块 例如 split d l 50 enwiki 2
  • 使用无效命令进行 fork 会导致 valgrind 中的内存泄漏

    我有以下代码 它在分叉内执行无效命令 以下代码在 valgrind 中返回内存泄漏 include
  • 使用 WGET 运行 cronjob PHP

    我尝试执行一个 cron 并每 5 分钟运行一个 url 我尝试使用 WGET 但我不想下载服务器上的文件 我只想运行它 这是我使用的 crontab 5 wget http www example com cronit php 除了 wg
  • 从 Java 读取 /dev/input/js0

    我正在尝试阅读 dev input js0来自Java 但我不断得到 java io IOException Invalid argument at java io FileInputStream read0 Native Method a
  • 命令行参数中的“-”(破折号)有什么魔力?

    例子 创建 ISO 映像并将其直接刻录到 CD mkisofs V Photos r home vivek photos cdrecord v dev dev dvdrw 更改到上一个目录 cd 侦听端口 12345 并解压发送到该端口的数
  • 使用 gatttool 或 bluepy BLE 订阅通知

    我正在使用 bluepy 编写一个程序 用于监听蓝牙设备发送的特征 我还可以使用任何库或语言 唯一的限制是在 Linux 上运行 而不是在移动环境中运行 似乎仅在移动设备中广泛使用 没有人在桌面上使用 BLE 使用 bluepy 我注册了委
  • 类似 wget 的 BitTorrent 客户端或库? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 是否有任何
  • 在 Linux 2.6.21 (glibc 2.3.5) 上进行 ARP 和反向 ARP

    我需要在任意 IP 网络上存储对第三方设备的持久引用 其中设备的 IP 地址可能是静态的或由 DHCP 随机分配 我不控制网络上的设备 也不能依赖 DNS 和其他现有的或与设备一起使用的临时网络协议 所以我被指示使用硬件地址和 ARP 进行
  • Linux:通过网络进行屏幕桌面视频捕获和 VNC 帧速率

    抱歉 文字墙很长 TL DR VNC 连接的帧速率是多少 以帧 秒为单位 或者更确切地说 由谁决定 客户端还是服务器 对于桌面屏幕捕获的任何其他建议 但 正确的时间编码 具有不抖动的帧速率 具有稳定的周期 并有可能将其作为未压缩 或无损 图
  • 访问 Linux 线程(pthreads)的本地堆栈

    我目前正在实现一个使用多线程但对总内存消耗有要求的应用程序 我希望有一个主线程执行 I O 并有几个工作线程执行计算 目前 我在主堆栈上有几个可供工作人员访问的数据结构 我使用 OpenMP 进行工作分配 由于主 工作者模式不能很好地与 O
  • 如何真正释放 Linux 中的大页面以供新进程使用?

    真的找不到太多关于此的信息 希望有人可以提供帮助 我正在假脱机使用 100GB java 堆作为大数据缓存 为了避免与文件系统缓存等内容发生冲突 并且因为它通常性能更好 我将其分配在大页面中 我保留了 51 200 x 2MB 大页面 一切
  • 在键盘热插拔上加载模块

    我正在尝试学习如何为 Linux 系统编写模块和驱动程序 类似于this https unix stackexchange com questions 120839 usb kernel module does not load on de
  • Alsa 带有来自调制解调器的 PCM 接口

    我有一个基于 imx28 CPU 的定制板 CPU 的串行端口连接到调制解调器的 PCM 输出 我必须为调制解调器的 PCM 接口开发一个驱动程序 使其成为 ALSA SoC 的一部分 您能指出内核树 中与我的设置重新组合的一些驱动程序吗
  • 如何删除树莓派的相机预览

    我在我的 raspberryPi 上安装了 SimpleCv 并安装了用于使用相机板的驱动程序 uv4l 驱动程序 现在我想使用它 当我在 simpleCV shell Camera 0 getImage save foo jpg 上键入时
  • 如何使用libaudit?

    我试图了解如何使用 libaudit 我想接收有关使用 C C 的用户操作的事件 我不明白如何设置规则 以及如何获取有关用户操作的信息 例如 我想获取用户创建目录时的信息 int audit fd audit open struct aud
  • 测试linux下磁盘空间不足

    我有一个程序 当写入某个文件的磁盘空间不足时 该程序可能会死掉 我不确定是否是这种情况 我想运行它并查看 但我的测试服务器不会很快耗尽空间 有什么办法可以嘲笑这种行为吗 看起来没有任何方法可以在 Ubuntu 中设置文件夹 文件大小限制 并
  • Linux TCP服务器:在接受连接之前读取客户端的IP地址

    Related C Winsock API如何在接受连接之前获取连接客户端IP https stackoverflow com questions 716209 c winsock api how to get connecting cli
  • 如何使用 bash 脚本关闭所有终端,在每个终端中有效地按 Ctrl+Shift+Q

    我经常打开许多终端 其中一些正在运行重要的进程 例如服务器 而另一些则没有运行任何东西并且可以关闭 如果您按 重要 则会弹出确认提示Cntrl Shift Q在其中 如下所示 我想要一个 bash 脚本 它可以关闭所有终端 但将 重要 终端

随机推荐

  • Elasticsearch知识点

    目录 1 什么是Elasticsearch 2 Elasticsearch的特点 3 Elasticsearch基础概念 4 Elasticsearch基本数据类型 看这里 5 Elasticsearch基本检索类型 5 1 检索和过滤 5
  • python编译javascript_Js2Py - 把js代码翻译成python代码。也让你可以在python环境里运行js代码。...

    Pure Python JavaScript Translator Interpreter Everything is done in 100 pure Python so it s extremely easy to install an
  • top 命令解释和案例

    文章目录 Top结果 Task分析 CPU分析 内存分析 Top结果 在Linux系统中 top命令用于实时监控系统的性能和进程活动 当你在终端运行top命令时 会显示一个实时的进程列表和系统性能指标 top结果的详细描述如下 第一行 显示
  • Elasticsearch的配置及常见错误

    1 下载Elasticsearch到d盘 在elasticsearch yml中配置两项内容 其中cluster name对应springboot项目中application properties里elasticsearch配置的 elas
  • Java 日期 不同月按周分组

    日期按月 按周次分组 今天接到需求 要求按月份分开周次 12月31号和新一年的1月1号拆开两个组 2020 12 第五周 2020 12 28 2020 12 31 2021 01 第一周 2021 01 01 2021 01 03 咋一看
  • 设计模式——反射

    本文说明 在学习 Java EE互联网轻量级框架整合开发 此书时 里面提到了几种设计模式 我在学习这几种设计模式时写了笔记 放上来让大家共同学习 如果有错误 望指出 本章由两部分组成 1 基本概念 关键代码讲解 2 完整例子 基本概念 关键
  • vue3-实战-04-管理后台表单校验-layout-菜单组件封装

    目录 1 自定义校验规则 2 layout组件静态页面搭建 3 logo组件封装 4 左侧菜单静态组件搭建 4 1 动态获取菜单数据 4 2 封装菜单动态展示组件 4 3 配置菜单名称 隐藏 图标属性 4 4 菜单刷新定位当前菜单 5 内容
  • python大数据毕业设计题目100例

    文章目录 0 前言 1 python 算法类 毕设选题 2 python 数据挖掘 毕设选题 3 python 大数据处理 云计算 区块链 毕设选题 4 python 网络安全 毕设选题 5 python 游戏设计 动画设计类 毕设选题 适
  • mysql求两个表的不同记录

    问题是 现在有两个表 一个是记录昨天的记录 一个是记录今天的记录 如何求 1 新增的记录 今天有 昨天没有的记录 2 减少的记录 今天没有 昨天有的记录 求解该类问题 需要用到sql的连接查询 为了简单起见 使用user1表和user2表来
  • 更新linux内核方法

    背景 买了块网件的A6210无线网卡 用的是mt7612u芯片 插到deepin下不能识别 ubuntu 18 04下同样不能识别 查过内核版本号 用的都是4 15的内核 去Github查了Linux内核仓库 确认4 15内核里没有mt76
  • PHP网上花店管理系统 毕业设计源码21170

    目 录 摘要 1 绪论 1 1研究背景 1 2项目背景 1 3 Thinkphp框架介绍 1 4论文结构与章节安排 2 网上花店管理系统系统分析 2 1 可行性分析 2 2 系统流程分析 2 2 1数据增加流程 2 2 2数据修改流程 2
  • C++ STL编程轻松入门基础

    来源 天极网 作为C 标准不可缺少的一部分 STL应该是渗透在C 程序的角角落落里的 STL不是实验室里的宠儿 也不是程序员桌上的摆设 她的激动人心并非昙花一现 本教程旨在传播和普及STL的基础知识 若能借此机会为STL的推广做些力所能及的
  • 【华为OD机试真题2023B卷 JAVA&JS】解压报文

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 解压报文 知识点栈 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 为了提升数据传输的效率 会对传输的报文进行压缩处理 输入一个压缩后的报文 请返回它解压后的原始报文
  • 讯飞版大模型来了,现场发布四大行业应用成果

    文章目录 人工智能福利文章 前言 SparkDesk讯飞星火认知大模型简介 语言理解 知识问答 逻辑推理 数学题解答 代码理解与编写 亲自体验 写在最后 创作者 全栈弄潮儿 个人主页 全栈弄潮儿的个人主页 个人社区 欢迎你的加入 全栈弄潮儿
  • 梯度下降的作用及分类

    一 介绍 梯度下降法是一个最优化算法 通常也称 最速下降法 常用于机器学习和人工智能中递归性逼近最小偏差模型 梯度下降的方向就是用负梯度方向为搜索方向 沿着梯度下降的方向求解极小值 在训练过程中 每次的正向传播都会得到输出值和真实值的损失值
  • keras使用callbacks后报错:tensorflow.python.framework.errors_impl.NotFoundError: Failed to create a direct

    参考 https stackoverflow com questions 59439124 keras tuner search function throws failed to create a newwriteablefile err
  • Maven引入本地jar包的方法分享

    转自 maven中如何包含本地jar包呢 有时候我们的jar包来源于maven仓库 有时候来源于本地仓库 有时候来源于本地文件 来源于仓库的文件 我们只需输入相应的坐标即可 那么jar包来源于本地文件 如何处理呢 下文笔者讲述maven中包
  • 二十三种设计模式第二十一篇--解释器模式

    解释器模式 Interpreter Pattern 是一种行为设计模式 它用于定义一种语言的语法结构和解释器 使得可以解释并执行特定的语法规则 该模式可以将复杂的语言表达式分解为更小的语法单元 并定义其解释过程 解释器模式的核心组成部分包括
  • NameError: global name ‘***‘ is not defined

    错误示范 class Solution object def fib self n type n int rtype int while n gt 0 if n 1 or n 2 return 1 else return fib n 1 f
  • 手把手带你实现Linux内核编译步骤及配置

    linux 系统体系结构 linux kernel体系结构 arm有7种工作模式 x86也实现了4个不同级别RING0 RING3 RING0级别最高 这样linux用户代码运行在RING3下 内核运行在RING0 这样系统本身就得到了 充