searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

linux内核编译简介

2023-03-31 06:00:11
33
0
一、linux内核基本功能
 
1、管理进程:
内核负责创建和销毁进程, 并处理它们与外部世界的联系(输入和输出),不同进程间通讯(通过信号,管道,或者进程间通讯原语)对整个系统功能来说是基本的,也由内核处理。 另外, 调度器, 控制进程如何共享CPU,是进程管理的一部分。更通常地,内核的进程管理活动实现了多个进程在一个单个或者几个CPU 之上的抽象。
2、管理内存:
计算机的内存是主要的资源, 处理它所用的策略对系统性能是至关重要的。内核为所有进程的每一个都在有限的可用资源上建立了一个虚拟地址空间。内核的不同部分与内存管理子系统通过一套函数调用交互,从简单的malloc/free对到更多更复杂的功能。
3、文件系统:
Unix 在很大程度上基于文件系统的概念;几乎Unix中的任何东西都可看作一个文件。内核在非结构化的硬件之上建立了一个结构化的文件系统,结果是文件的抽象非常多地在整个系统中应用。另外,Linux 支持多个文件系统类型,就是说,物理介质上不同的数据组织方式。例如,磁盘可被格式化成标准Linux的ext3文件系统,普遍使用的FAT文件系统,或者其他几个文件系统。
4、设备控制:
几乎每个系统操作终都映射到一个物理设备上,除了处理器,内存和非常少的别的实体之外,全部中的任何设备控制操作都由特定于要寻址的设备相关的代码来进行。这些代码称为设备驱动。内核中必须嵌入系统中出现的每个外设的驱动,从硬盘驱动到键盘和磁带驱动器。
5、网络管理:
网络必须由操作系统来管理,因为大部分网络操作不是特定于某一个进程: 进入系统的报文是异步事件。报文在某一个进程接手之前必须被收集,识别,分发,系统负责在程序和网络接口之间递送数据报文,它必须根据程序的网络活动来控制程序的执行。另外,所有的路由和地址解析问题都在内核中实现。
 
二、内核编译需求
 
        编译内核可能是出于某种需求,比如对内核大小有要求,去掉内核中某些用不到的部分,这种场景往往是嵌入式系统。或者自己修改了某部分内核代码,需要编译后验证功能。模块编译时将某些功能模块编译成 .ko 可以在不重新编译内核的情况下,insmod xxx.ko 到系统中使用编写的代码功能。编译内核后不会替换当前内核,编译后的新内核往往在类似下面的目录下,名字大都是 bzImage /usr/src/kernels/3.xx.x-.x86_64/arch/x86/boot/ ,然后可以编辑系统的 grub list 添加最新的内核来用它
 
三、内核编译流程
 
1.下载对应版本的内核镜像
2.将下载的内核 Linux 保存到 /usr/src/ 目录下: (/usr/src 一般就是用来存放Linux的内核源码)
tar xvf linux-6.1.0.tar.xz -C /usr/src/
cd /usr/src/
ln -sv linux-6.1.0 linux
3.进入Linux目录下: cd /usr/src/linux
4.安装依赖包
yum groupinstall Development Tools
yum install ncurses-devel
yum install elfutils-libelf-devel-0.176-5.el7.x86_64
yum install openssl-devel
yum install bc-1.06.95-13.el7.x86_64
5.执行 make menuconfig 配置需要的功能
*表示在选择编译到内核中 M表示以模块的形式存在
嵌入式设备内核中很多不需要的选择取消勾选
配置完成后会生成.config的隐藏文件,如果不知道该开启哪些功能也可以直接选用当前系统的配置文件,这里直接使用当前系统的配置文件。
6.编译内核
7.安装内核
make modules_install
make install 
8. 查看当前内核版本
安装完后会在/boot目录下生成新的内核文件
9. 重启reboot
10.查看编译后的内核版本
四、内核驱动编译
1.编写一个demo_driver.c的驱动程序
/**********************************************************************************************************
Includes 
**********************************************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>

/**********************************************************************************************************
Define
**********************************************************************************************************/
#define    DRIVER_MAJOR     255
#define    DEVICE_NAME     "demo_driver"


/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static int demo_open(struct inode *inode, struct file *file)
{
printk(KERN_EMERG "======================demo_open======================\n");
return 0;
}
/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static ssize_t demo_write(struct file *file, const char __user * buf, size_t count, loff_t *ppos)
{
    printk(KERN_EMERG "======================demo_write======================\n");
    return 0;
}
/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static ssize_t demo_read(struct file *file,  char __user * buf, size_t count, loff_t *ppos)
{
    printk(KERN_EMERG "======================demo_read ======================\n");  
    return 0;
}
/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static int demo_close(struct inode *inode, struct file *file)
{
    printk(KERN_EMERG "======================demo_close ======================\n");
    return 0;
}

/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static struct file_operations demo_flops = 
{
.owner  =   THIS_MODULE,
.open   =   demo_open,     
.write  =   demo_write,
.read =  demo_read,
.release =  demo_close,
};

/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static int __init demo_init(void)
{
    int ret;
 
//注册设备
    ret = register_chrdev(DRIVER_MAJOR,DEVICE_NAME, &demo_flops);

    if (ret < 0) 
{
      printk(KERN_EMERG DEVICE_NAME " can't register major number.\n");
      return ret;
    }
else
{
printk(KERN_EMERG DEVICE_NAME " ======================demo init======================\n");
}

    return 0;
}
/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static void __exit demo_exit(void)
{
    unregister_chrdev(DRIVER_MAJOR, DEVICE_NAME);
    printk(KERN_EMERG DEVICE_NAME " ======================demoexit======================\n");
}


module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
/***********************************************END*******************************************************/
使用printk时,Linux内核根据日志级别,可能把消息打印到当前控制台上,这个控制台是一个字符设备。这些消息从终端输出的前提是日志输出级别小于console_loglevel。日志级别有八个:0-7(越小级别越高)
#define KERN_EMERG    KERN_SOH "0"    /* system is unusable                通常是系统崩溃前的信息 */
#define KERN_ALERT    KERN_SOH "1"    /* action must be taken immediately  需要立即处理的消息 */
#define KERN_CRIT    KERN_SOH "2"    /* critical conditions 严重情况 */
#define KERN_ERR    KERN_SOH "3"    /* error conditions     错误情况 */
#define KERN_WARNING    KERN_SOH "4"    /* warning conditions 有问题的情况 */
#define KERN_NOTICE    KERN_SOH "5"    /* normal but significant condition 注意信息 */
#define KERN_INFO    KERN_SOH "6"    /* informational 普通消息 */
#define KERN_DEBUG    KERN_SOH "7"    /* debug-level messages 调试信息 */
2. 编写Makefile文件
obj-m   :=      demo_driver.o
KERNEL  :=      /usr/src/linux/
PWD     :=      $(shell pwd)
modules:
        $(MAKE) -C      $(KERNEL)       M=$(PWD)        modules
clean:
        rm      -f      *.o     *.ko
# Makefile语法要注意,不能使用空格键来控制文本行缩进,必须使用Tab键,否则会出现Makefile:5: *** missing separator
# /usr/src/linux/这里写死了, 可以这样 /usr/src/kernels/$(uname -r)/ ,因为是想用高版本内核所以才写死
3. make编译
4. 加载驱动
5. 查看设备
6. 移除驱动
0条评论
0 / 1000
顾****涵
5文章数
0粉丝数
顾****涵
5 文章 | 0 粉丝
原创

linux内核编译简介

2023-03-31 06:00:11
33
0
一、linux内核基本功能
 
1、管理进程:
内核负责创建和销毁进程, 并处理它们与外部世界的联系(输入和输出),不同进程间通讯(通过信号,管道,或者进程间通讯原语)对整个系统功能来说是基本的,也由内核处理。 另外, 调度器, 控制进程如何共享CPU,是进程管理的一部分。更通常地,内核的进程管理活动实现了多个进程在一个单个或者几个CPU 之上的抽象。
2、管理内存:
计算机的内存是主要的资源, 处理它所用的策略对系统性能是至关重要的。内核为所有进程的每一个都在有限的可用资源上建立了一个虚拟地址空间。内核的不同部分与内存管理子系统通过一套函数调用交互,从简单的malloc/free对到更多更复杂的功能。
3、文件系统:
Unix 在很大程度上基于文件系统的概念;几乎Unix中的任何东西都可看作一个文件。内核在非结构化的硬件之上建立了一个结构化的文件系统,结果是文件的抽象非常多地在整个系统中应用。另外,Linux 支持多个文件系统类型,就是说,物理介质上不同的数据组织方式。例如,磁盘可被格式化成标准Linux的ext3文件系统,普遍使用的FAT文件系统,或者其他几个文件系统。
4、设备控制:
几乎每个系统操作终都映射到一个物理设备上,除了处理器,内存和非常少的别的实体之外,全部中的任何设备控制操作都由特定于要寻址的设备相关的代码来进行。这些代码称为设备驱动。内核中必须嵌入系统中出现的每个外设的驱动,从硬盘驱动到键盘和磁带驱动器。
5、网络管理:
网络必须由操作系统来管理,因为大部分网络操作不是特定于某一个进程: 进入系统的报文是异步事件。报文在某一个进程接手之前必须被收集,识别,分发,系统负责在程序和网络接口之间递送数据报文,它必须根据程序的网络活动来控制程序的执行。另外,所有的路由和地址解析问题都在内核中实现。
 
二、内核编译需求
 
        编译内核可能是出于某种需求,比如对内核大小有要求,去掉内核中某些用不到的部分,这种场景往往是嵌入式系统。或者自己修改了某部分内核代码,需要编译后验证功能。模块编译时将某些功能模块编译成 .ko 可以在不重新编译内核的情况下,insmod xxx.ko 到系统中使用编写的代码功能。编译内核后不会替换当前内核,编译后的新内核往往在类似下面的目录下,名字大都是 bzImage /usr/src/kernels/3.xx.x-.x86_64/arch/x86/boot/ ,然后可以编辑系统的 grub list 添加最新的内核来用它
 
三、内核编译流程
 
1.下载对应版本的内核镜像
2.将下载的内核 Linux 保存到 /usr/src/ 目录下: (/usr/src 一般就是用来存放Linux的内核源码)
tar xvf linux-6.1.0.tar.xz -C /usr/src/
cd /usr/src/
ln -sv linux-6.1.0 linux
3.进入Linux目录下: cd /usr/src/linux
4.安装依赖包
yum groupinstall Development Tools
yum install ncurses-devel
yum install elfutils-libelf-devel-0.176-5.el7.x86_64
yum install openssl-devel
yum install bc-1.06.95-13.el7.x86_64
5.执行 make menuconfig 配置需要的功能
*表示在选择编译到内核中 M表示以模块的形式存在
嵌入式设备内核中很多不需要的选择取消勾选
配置完成后会生成.config的隐藏文件,如果不知道该开启哪些功能也可以直接选用当前系统的配置文件,这里直接使用当前系统的配置文件。
6.编译内核
7.安装内核
make modules_install
make install 
8. 查看当前内核版本
安装完后会在/boot目录下生成新的内核文件
9. 重启reboot
10.查看编译后的内核版本
四、内核驱动编译
1.编写一个demo_driver.c的驱动程序
/**********************************************************************************************************
Includes 
**********************************************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>

/**********************************************************************************************************
Define
**********************************************************************************************************/
#define    DRIVER_MAJOR     255
#define    DEVICE_NAME     "demo_driver"


/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static int demo_open(struct inode *inode, struct file *file)
{
printk(KERN_EMERG "======================demo_open======================\n");
return 0;
}
/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static ssize_t demo_write(struct file *file, const char __user * buf, size_t count, loff_t *ppos)
{
    printk(KERN_EMERG "======================demo_write======================\n");
    return 0;
}
/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static ssize_t demo_read(struct file *file,  char __user * buf, size_t count, loff_t *ppos)
{
    printk(KERN_EMERG "======================demo_read ======================\n");  
    return 0;
}
/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static int demo_close(struct inode *inode, struct file *file)
{
    printk(KERN_EMERG "======================demo_close ======================\n");
    return 0;
}

/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static struct file_operations demo_flops = 
{
.owner  =   THIS_MODULE,
.open   =   demo_open,     
.write  =   demo_write,
.read =  demo_read,
.release =  demo_close,
};

/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static int __init demo_init(void)
{
    int ret;
 
//注册设备
    ret = register_chrdev(DRIVER_MAJOR,DEVICE_NAME, &demo_flops);

    if (ret < 0) 
{
      printk(KERN_EMERG DEVICE_NAME " can't register major number.\n");
      return ret;
    }
else
{
printk(KERN_EMERG DEVICE_NAME " ======================demo init======================\n");
}

    return 0;
}
/***********************************************************************************************************
* @描述:  
***********************************************************************************************************/
static void __exit demo_exit(void)
{
    unregister_chrdev(DRIVER_MAJOR, DEVICE_NAME);
    printk(KERN_EMERG DEVICE_NAME " ======================demoexit======================\n");
}


module_init(demo_init);
module_exit(demo_exit);
MODULE_LICENSE("GPL");
/***********************************************END*******************************************************/
使用printk时,Linux内核根据日志级别,可能把消息打印到当前控制台上,这个控制台是一个字符设备。这些消息从终端输出的前提是日志输出级别小于console_loglevel。日志级别有八个:0-7(越小级别越高)
#define KERN_EMERG    KERN_SOH "0"    /* system is unusable                通常是系统崩溃前的信息 */
#define KERN_ALERT    KERN_SOH "1"    /* action must be taken immediately  需要立即处理的消息 */
#define KERN_CRIT    KERN_SOH "2"    /* critical conditions 严重情况 */
#define KERN_ERR    KERN_SOH "3"    /* error conditions     错误情况 */
#define KERN_WARNING    KERN_SOH "4"    /* warning conditions 有问题的情况 */
#define KERN_NOTICE    KERN_SOH "5"    /* normal but significant condition 注意信息 */
#define KERN_INFO    KERN_SOH "6"    /* informational 普通消息 */
#define KERN_DEBUG    KERN_SOH "7"    /* debug-level messages 调试信息 */
2. 编写Makefile文件
obj-m   :=      demo_driver.o
KERNEL  :=      /usr/src/linux/
PWD     :=      $(shell pwd)
modules:
        $(MAKE) -C      $(KERNEL)       M=$(PWD)        modules
clean:
        rm      -f      *.o     *.ko
# Makefile语法要注意,不能使用空格键来控制文本行缩进,必须使用Tab键,否则会出现Makefile:5: *** missing separator
# /usr/src/linux/这里写死了, 可以这样 /usr/src/kernels/$(uname -r)/ ,因为是想用高版本内核所以才写死
3. make编译
4. 加载驱动
5. 查看设备
6. 移除驱动
文章来自个人专栏
系统内核
2 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0