Linux 内核开发—内核简单介绍

内核简单介绍

Linux 构成

Linux 为什么被划分为系统空间和内核空间

隔离核心程序和应用程序,实现对核心程序和数据的保护。

什么内核空间,用户空间

内核空间和用户空间是程序执行的两种不同的状态,Linux对自身软件系统进行了划分,一部分核心的软件独立于普通的软件,拥有特权级别,可以訪问平台的全部硬件和资源,称为“内核空间”。而普通的软件执行在“用户空间”,它仅仅拥有有限的系统资源,不能直接訪问内核空间和硬件资源。

将系统分为“内核空间”和“系统空间”能提高系统的安全性,可以避免一些恶意程序的窥探,也能避免一些低劣的普通程序影响核心系统的执行,可以有效的保证系统的稳定性。

内核构成

SCI:

为用户空间提供了一套统一的系统调用函数来訪问Linux内核,是用户空间到内核空间的桥梁。

Glibc:

是GNU公布的libc库,也是C执行库,是Linux中最底层的API,差点儿全部的app都依赖于Glibc,它除了封装Linux系统提供的系统函数以外,其自身也提供了非常多其它的功能的函数库,基本的库函数例如以下:

(1)string库,字符串处理库函数

(2)signal库,提供信号处理库函数

(3)dlfcn库,管理共享库的动态载入函数库

(4)directory库,文件文件夹操作函数

(5)elf库,共享库的动态载入器,也即interpreter

(6)iconv,不同字符集的编码转换

(7)sockets,socket接口库

(8)Date and Time,日期和时间

(9)input/output,输入输出流

(10)linux threads库,LINUX线程库函数

(11)locale库,本地化和国际化的接口库

(12)Character库,字符处理

(13)Memory库,动态内存的分配与管理

(14)Processes and job control库,进程和进程控制库

(15)stdlib库,其他基本功能

内存管理:

控制多个进程安全的共享有限的内存区域。

进程管理:

进程管理的主要任务包含进程的创建、停止、进程间通信,还包含不同的进程共享CPU。

VFS:

虚拟文件系统隐藏了不同文件系统的细节,为文件操作提供了统一的接口。

网络协议栈:

提供丰富的网络协议实现。

设备驱动:

内核中大量的源代码都是在驱动中实现的,它们控制着特定的硬件设备。

ARM 有哪些工作模式

用户模式(user)

高速中断模式(frq)

外部中断模式(irq)

管理模式(svc)

数据訪问终止(abt)

系统模式(sys)

为定义指令异常(und)

不同模式下有不同权限,如寄存器权限

内核空间和用户空间怎样转换

硬件中断和系统调用能够实现用户空间跳转到内核空间执行

Linux内核源码

内核源码下载地址:www.kernel.org

内核文件夹结构

Arch(Architecture):内核支持的每一种CPU体系,在该文件夹下都有一个子文件夹,每一个不同的CPU子文件夹又都分为boot(系统引导)、mm(内存管理)、kernel(内核特性相关实现)等子文件夹。

|--x86 /*英特尔CPU及与其体系结构兼容的子文件夹*/

||--boot /*引导程序*/

|||--compressed /*内核解压缩*/

||--tools /*生成压缩内核印象的程序*/

||--kernel /*内核特性相关的实现,如信号处理、时钟处理*/

||--lib /*硬件相关工具函数*/

文件夹结构

Linux source code

├─ boot 系统引导汇编程序

├─ fs 文件系统

│ ├─ devpts /*/dev/pts虚拟文件系统*/

│ ├─ ext2 第二扩展文件系统

│ ├─ fat MS 的fat32文件系统

├─ block 部分块设备驱动程序

├─ crypto 加密、压缩、CRC校验算法

├─ 内核的文档

├─ drivers 设备驱动程序

├─ include 头文件(*.h) 内核所需的头文件,与平台相关的头文件放在对应的字文件夹下

│ ├─ asm 与CPU 体系结构相关的部分

│ ├─ linux  Linux 内核专用部分,与平台无关的头文件

│ └─ sys 系统数据结构部分

├─ init 内核初始化程序

├─ IPC 进程间通信的实现代码

├─ samples 一些内核编程的范例

├─ scripts 配置内核的脚本

├─ sound 音频设备的驱动程序

├─ usr cpio 命令实现

├─ virt 内核虚拟机

├─ kernel 内核进程调度、信号处理、系统调用等程序

│ ├─ blk_drv 块设备驱动程序

│ ├─ chr_drv 字符设备驱动程序

│ └─ math 数学协处理器仿真处理程序

├─ lib 内核库函数

├─ mm 内存管理程序

└─ tools 生成内核Image 文件的工具程序

Linux内核配置与编译

硬件的软硬件的配置情况,比方CPU的型号、网卡的型号、支持的网络协议等。

内核配置相关命令

1)清除类命令

make clean :清除kernel文件夹下大部分编译生成的文件。

make mrproper :清除全部编译生成的文件+配置文件(config等相关文件)。

make distclean :清除全部backup 文件 + patch 文件 + make mrproper

2)配置命令

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

make menuconfig :基于文本模式的菜单性配置模式(推荐使用)。

make oldconfig :与 make config 类似,使用已有的配置文件进行配置,对于新增的菜单会进行提示。

make xconfig :基于图形化界面的配置方式,需呀安装图形化工具。

make menuconfig 是最经常使用的内核配置命令,能够使用方向键上/下移动,“Enter”进入文件夹,每一个配置选项能够选择“y”、“m”、“n”,也能够使用空格在这三个选项中进行切换。而且能够使用“h”显示这个选项的说明。

“y” :表示会被编译进内核的镜像文件。

“m” :表示会被编译成内核模块,不会放在内核的镜像文件的。

“n” :(空白) 表示不会对此模块进行编译,更不会放在内核镜像中。

内核配置选项说明

一般在开发的时候不会从无到有又一次配置全部的选项,而是在一个已有的配置文件基础之上依据实际的需求进行改动得到新的配置文件。Linux提供了一系列的配置文件模板,放在:Arch/$(cpu)/configs

内核镜像文件

对于Linux内核,编译能够生成不同的镜像文件

  • zImage :

ARM Linux经常使用的一种镜像格式,它的大小不能超过512KB,使用gzip压缩

  • bzImage :

即bigImage,没有512KB限制大小,使用gzip压缩

  • uImage :

U-boot 专用的镜像压缩格式,他是在镜像文件的头部加上了一个大小为0x40的数据块,记录了镜像文件的类型、载入位置、生成时间、大小等信息。去掉这个0x40的头部实际和zImage没有差别。

  • vmlinux:

是一个Elf格式的可运行文件,编译完毕后会将全部的内核模块链接到一个vmlinux中。

  • vmlinuz:

vmlinux是一个可引导的、压缩的镜像文件,它是vmlinux的压缩文件。vm 是“virtual memory”的简写,由于Linux 支持虚拟内存,能够使用硬盘作为虚拟内存,因此得名“vm”,实际上zImage和bzImage都是vmlinuz的别称,zImage和bzImage都是採用gzip压缩,在其文件的头部有解压缩代码。

对于更直观的联系请參考下图:

内核的编译

1)    编译内核镜像

编译内核命令:

  • make zImage
  • make bzImage
  • make uImage

假设要获取具体的内核编译信息能够使用

  • make zImage V=1
  • make bzImage V=1

编译好的内核会放在arch/$(cpu)/boot/文件夹下

2)    编译内核模块

  • make modules

3)    安装内核模块

make modules_install

4)    查看内核版本号

  • cat /proc/version
  • uname –a
  • uname -r

虚拟内存盘(Ramdisk/Ramfs)

Ramdisk 是将一部分内存(RAM)虚拟成硬盘来使用的技术,相对于直接的硬盘訪问来说,ramdisk的訪问速度要高非常多,只是因为RAM的易失性,断电后ramdisk上的内容不会被保存。

Linux 上的Ramdisk主要是指linux rootfs,它包括了除内核以外全部的linux系统在引导和管理师须要的工具(一般会使用busybox来完毕ramdisk的创建)

根文件系统

1)根文件系统概念

根文件系统是其它文件系统的根,它包括了系统引导和挂载其它文件系统的必要文件。根文件系统包括了linux启动时必要的文件夹和关键性文件,所以它必须是第一个载入的文件系统。

内核的安装

1)怎样载入执行内核镜像

内核模块

什么是内核模块

内核模块就是为内核或者其它内核模块提供功能的代码块,内核模块具有举例的功能,能独立的编译,可是须要在内核环境下才干执行。它在执行时被链接进内核作为内核的一部分在内核空间执行。内核模块的存在提高了单内核可可扩展性差、可维护性差的缺陷。

怎样使用内核模块

方法一:

将全部的内核组件都编译进内核,生成zImage或者bzImage文件。

缺陷:内核文件过大、新增/删除内核组件的时候须要又一次编译源代码

方法二:

zImage或者bzImage文件并不包括不论什么组件,仅仅是在须要用到某个组件的时候,动态的将内核组件加入到内核中去。

内核模块的特点

1)模块本身并不被编译进内核文件

2)可依据需求,在内核执行期间,动态的加入或者卸载

内核模块缺陷

添加了管理内核模块的开销

内核版本号与模块版本号不兼容,会导致系统崩溃

添加内存、中断、符号表等资源消耗

内核模块的编译

Makefile

ifneq ($(KERNELRELEASE),)
#“hello”是模块的名称,仅仅有“hello”可变。
obj-m := hello.o
hello-objs := file1.o file2.o

else

#内核源码的位置
KDIR := ~/kernel/
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.c *.mod.o *.symvers
endif

内核模块的安装与卸载

命令:

1) insmod 载入内核模块

2) rmmod 卸载内核模块

3)lsmod 查看已经存在的内核模块

4)modprobe 载入内核模块

modprobe 与 insmod的差别在于,modprobe能处理内核模块之间的依赖关系,它可以依据/lib/modules/version/modules.dep 文件所描写叙述的依赖关系来载入此模块所需的其它内核模块。

内核模块与应用程序的区别

1) 应用程序在运行完毕后会从内存中消失

2) 内核模块会在运行该模块前将其注冊到内核中去,当完毕初始化函数后仍然处于内核中,直到被卸载

内核模块相关宏

1) MODULE_LICENSE("GPL");

2) MODULE_AUTHOR("Jack Chen");

3) MODULE_DESCRIPTION("Hello World");

4) MODULE_ALIAS("A simple module");

5) MODULE_VERSION("V1.0");

带參数的内核模块

能够使用宏module_param(name,type,perm)声明输入參数,当中:

1) name 表示參数的名称

2) type 表示參数的类型,常见的类型有int(整形),charp(字符串类型)

3) perm 訪问权限

a) S_IRUGO 不论什么用户都对/sys/module中出现的该參数具有读权限

b) S_IWUSR 同意root用户改动/sys/module 中出现的该參数

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

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jack Chen");
MODULE_DESCRIPTION("Hello World");
MODULE_ALIAS("A simple module");
MODULE_VERSION("V1.0");

static int age = 10;
static char* name = "Jack chen";

module_param(age,int,S_IRUGO);
module_param(name,charp,S_IRUGO);

static int hello_init(void)
{
printk(KERN_EMERG" age:%d\n",age);
printk(KERN_EMERG" name:%s\n",name);
return 0;
}

static void hello_exit(void)
{
printk("<3>Goodbye,world !\n");
}

module_init(hello_init);
module_exit(hello_exit);

PS:使用insmod命令时的语法为 insmod hello.ko age=27 name=”David”

内核模块的导出

用于向其它内核模块提供功能函数,否则其它内核模块无法使用模块内的功能函数,当中/proc/kallsyms记录了内核中全部导出符号的名字和地址。

1) EXPORT_SYMBOL(符号名)

2) EXPORT_SYMBOL_GPL(符号名) 适用于包括了GPL许可证的的内核模块

使用EXPORT_SYMBOL声明后的符号将加入在/proc/kallsyms 文件里,能够使用cat/proc/kallsyms | grep “符号名” 查询

[calculate.c]

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

MODULE_LICENSE("GPL");                                

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

int sub_integar(int a,int b)
{
return a-b;
}                            

static int __init sym_init()
{
    return 0;
}

static void __exit sym_exit()
{

}

module_init(sym_init);
module_exit(sym_exit);

EXPORT_SYMBOL(add_integar);
EXPORT_SYMBOL(sub_integar);
 

[hello.c]

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

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jack Chen");
MODULE_DESCRIPTION("Hello World");
MODULE_ALIAS("A simple module");
MODULE_VERSION("V1.0");

extern int add_integar(int a,int b);
extern int sub_integar(int a,int b);

static int hello_init()
{
    int res = add_integar(1,2);
    printk("<3> res:%d\n",res);
    return 0;
}

static void hello_exit()
{
    int res = sub_integar(2,1);

    printk("<3> res:%d\n",res);
}

module_init(hello_init);
module_exit(hello_exit);

printk 的优先级

1) printk的日志级别定义例如以下(在linux26/includelinux/kernel.h中):

2) #defineKERN_EMERG"<0>"/*紧急事件消息,系统崩溃之前提示,表示系统不可用*/

3) #defineKERN_ALERT"<1>"/*报告消息,表示必须马上採取措施*/

4) #defineKERN_CRIT"<2>"/*临界条件,通常涉及严重的硬件或软件操作失败*/

5) #defineKERN_ERR"<3>"/*错误条件,驱动程序经常使用KERN_ERR来报告硬件的错误*/

6) #defineKERN_WARNING"<4>"/*警告条件,对可能出现故障的情况进行警告*/

7) #defineKERN_NOTICE"<5>"/*正常但又重要的条件,用于提醒。经常使用于与安全相关的消息*/

8) #defineKERN_INFO"<6>"/*提示信息,如驱动程序启动时,打印硬件信息*/

9) #defineKERN_DEBUG"<7>"/*调试级别的消息*/

时间: 2024-10-02 17:09:58

Linux 内核开发—内核简单介绍的相关文章

Linux 内核开发 - 内核定时器

时间差的度量 系统的定时器硬件以固定的频率产生时钟中断,产生始终中断的间隔以HZ 常量来决定,通常在50~1200之间,x86默认是1000,HZ可以根据不同的内核来配置. Linux 采用jiffies (unsigned long)来对时钟中断进行计数,每当发生时钟中断时jiffies的值将+1,因此jiffies就记录了系统开机以来的时钟中断总次数.在驱动开发过程中经常会使用时钟中断来计算不同事件的时间间隔. 延迟执行 对于不精确的时间延迟要求,可以使用while 循环来计算延迟的时间.

Linux 内核开发——内核简介

内核简介 Linux 构成 Linux 为什么被划分为系统空间和内核控件 隔离核心程序和应用程序,实现对核心程序的保护,如保护操作系统本身的保护. 什么内核空间,用户空间 内核空间和用户空间是程序运行的两种不同的状态,Linux对自身软件系统进行了划分,一部分核心的软件独立于普通的软件,拥有特权级别,能够访问平台的所有硬件和资源,称为"内核空间".而普通的软件运行在"用户空间",它只拥有有限的系统资源,不能直接访问内核空间和硬件资源. 将系统分为"内核空间

linux视频学习(简单介绍)20160405

看一周学会linux系统的学习笔记. 1.linux系统是一个安全性高的开源,免费的多用户多任务的操作系统. 2.linux工作分为linux系统管理员,linux程序员(PC上软件开发,嵌入式开发). 3.linux流程: linux平台上的开发,linux的基本操作. java/c语言学习. unix环境高级编程. linux应用系统开发.linux嵌入式开发. 4.linux的内容包括基础部分和实用部分. 基础部分:基础知识,常用linux命令,分区,vi,权限. 实用部分:Samba安装

第一阶段:前端开发_JDBC简单介绍

2018-06-25 JDBC简单介绍 一.什么是JDBC   JDBC(Java DataBase Connectivity)就是Java数据库连接,说白了就是用Java语言来操作数据库.  原来我们操作数据库是在控制台使用SQL语句来操作数据库,JDBC是用Java语言向数据库发送SQL语句. 二.JDBC原理 早期SUN公司的天才们想编写一套可以连接天下所有数据库的API,但是当他们刚刚开始时就发现这是不可完成的任务, 因为各个厂商的数据库服务器差异太大了.后来SUN开始与数据库厂商们讨论

Windows内核之线程简单介绍

1 线程定义 <1> 内核对象,操作系统用它来对线程实施管理.内核对象也是系统用来存放线程统计信息的地方 <2>还有一个是线程堆栈.它用于维护线程在运行代码时须要的全部函数參数和局部变量. 2 线程和进程的差别 <1>进程是不活泼的. 进程从来不运行不论什么东西.它仅仅是线程的容器. <2>线程在它的进程地址空间中运行代码,而且在进程的地址空间中对数据进行操作. <3>线程共享进程的地址控件 <4>线程仅仅有一个内核对象和一个堆栈,保

Android开发布局简单介绍

Android开发布局介绍 1.线性布局 LinearLayout 布局中的组件会一个挨着一个排列起来,android:orientation属性可以控制排列方向,horizontal-水平.vertical-垂直 线性布局不会自动换行,当超出屏幕范围时,剩下的组件不会显示出来. 2.表格布局 TableLayout 继承自LinearLayout,其本质依然是LinearLayout.通过TableRow来管理表格的行数和列数.添加一个TableRow就是一行. 3.帧布局 FrameLayo

iOS开发-UIActionSheet简单介绍

UIActionSheet和UIAlertView都是ios系统自带的模态视图,模态视图的一个重要的特性就是在显示模态视图的时候可以阻断其他视图的事件响应.一般情况下我们对UIAlertView使用的比较多,UIActionSheet相对来说情况少一点,偶尔作为一个上拉菜单来展示还是非常有用的.通常如果显示一个模态的视图,可以自定义一个UIViewController,不过里面的内容和动画实现起来工作量还是非常多的. UIActionSheet介绍 介绍UIActionSheet之前需要简单的看

linux文件系统的权限简单介绍

linux系统下,文件的权限是这样表示的: - --- --- --- 一共用10位的二进制进行表示,其中 位置 0 :  - :文件        d :目录剩下的9个位置:位置1-3 当前用户(应用程序自身)r:可读,W:可写.x:可执行.位置4-6 当前用户用户所在的组      r:可读,W:可写.x:可执行位置7-9 其他用户的权限               r:可读,W:可写.x:可执行 当某个位置存在值的时候,就代表1,不存在值的时候就代表0: 比如:- --- --- ---:

【高德地图开发】---简单介绍

高德地图 Android SDK 能够为 Android 应用开发人员提供互动的.功能丰富的 Android 手机地图. 将地图显示功能与搜索服务. 定位服务分别封装为三个类库.每一个类库不相互依赖,用户能够分开使用. 提供 2D(栅格)和3D(矢量)地图SDK.用户依据不同的需求选择不同的类库. 完美支持 Android 手机.平板电脑,可在不同屏幕尺寸下呈现完美的显示效果. 地图採用矢量方法绘制.使得地图处理速度更快.流量占用更少. 地图支持 3D 模式.通过移动用户的视角,能够从各个角度显