Linux 内核学习(6) --- Linux 内核基础知识

目录

      • Linux 内核基础知识
      • 进程调度
      • 内存管理
      • 虚拟文件系统和网络接口
      • 进程间通信
      • Linux 内核编译
      • Makefile 和 Kconfig
        • 内核Makefile
        • 内核Kconfig
      • 配置项标识的写法
        • depend 关键字
        • select 关键字
        • 表达式逻辑关系
        • Kconfig 其他语法
      • 配置文件的编译
      • Linux 内核引导方法
      • Booloader 定义
      • Linux 内核C编程特点
        • Linux 内核编码风格
        • 零长度数组和变量数组
        • 标号元素
        • 可变参数宏
        • 特殊属性声明
        • type of关键字
        • 内建函数
        • do...while(0)
      • Arm 处理器工作模式

Linux 内核基础知识

Linux 内核主要由调度(SCHED),内存管理(MM),虚拟文件系统(VFS),网络接口(Net),进程间通信(IPC)这5个子系统组成
Linux 内核各个部分的组成关系如下图所示:
Linux 内核部分组成关系.png

进程调度

进程调度控制系统中多个进程对CPU进行访问,使得CPU能够 微观串行,宏观并行的进行执行
linux 进程的状态切换如下图所示:
进程状态切换.png

内存管理

内存管理的作用是控制多个进程安全的共享主内存区域,当CPU提供内存管理单元(MMU)时,Linux 内存管理完成每个进程进行虚拟地址到物理内部的转换
一般而言,Linux 进程享有4GB 的内存空间,0-3G 属于内存空间,3-4G 属于内核空间,如下图所示:
Linux 进程地址空间.png

虚拟文件系统和网络接口

Linux 的虚拟文件系统(VFS)隐藏了硬件的具体细节,为所有的设备提供了统一的接口
网络接口提供了对各个网络标准的存取和对网络硬件的支持

进程间通信

Linux 支持多种进程间通信机制,包含 信号量、共享内存、管道等,这些机制可以协助多个进程,多资源的互斥访问、进程间的同步和消息传递

Linux 内核编译

内核编译方式分为两步 : 配置内核和编译内核
配置内核命令

make menuconfig
//或者如果有现成的配置文件 如 lddxxxx_defconfig
make lddxxxx_defconfig

编译内核和模块的方式是:

make zImage
make modules

编译完成后生成的文件:

  • 未压缩的内核镜像文件 vmlinux
  • 内核符号表文件 System.map
  • arch/arm/boot 下得到压缩镜像文件 zImage

Makefile 和 Kconfig

内核Makefile

内核Makefile 文件的规则
obj-y = foo.o 表示将 foo 编译并连接进内核
obj-m = foo.o 表示将 foo 以模块化编译 生成 ko 文件
更加通用的做法是:
obj-$(CONFIG_ISDN) = isdn.o

多文件的处理方法:
obj-$(CONFIG_EXT2_FS) += ext2.o

ext2-y := balloc.o dir.o file.o fsync.o ialloc.o inode.o
ioctl.o

ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o

添加目录的结构:
obj-$(CONFIG-EXT2_FS) += exte2/

内核Kconfig

内核Kconfig 项的基本格式

config  xxxxx
bool “xxxxxxxxxxxxx”
default n
depend on <expr>
select  xxxx
//举例如下
config DRM_DP_AUX_CHARDEVbool "DRM DP AUX Interface"depends on DRMhelpChoose this option to enable a /dev/drm_dp_auxN node that allows toread and write values to arbitrary DPCD registers on the DP auxchannel.
  • config 表示一个配置项目
    bool 表示的是数据类型,其他数据类型还包括 bool、tristate、string、hex、int, tristate 和 string** 是两种基本类型,其他类型都基于这两种类型
  • help 信息用于提示,格式如下:
    help ( 或者— help — )
    开始
    ….
    结束

配置项标识的写法

bool “DRM DP AUX Interface” 和
bool
prompt “DRM DP AUX Interface” 是一致的 prompt(英语含义:提示)
输入提示的一般格式为:
prompt [if ]

depend 关键字

default [if ] // 表示配置的默认值,一个配置选项可以存在任意多个默认的值,在这种情况下,生效的第一个的值
bool “foo” if BAR
default y if BAR
和下面的等价
depends on BAR
boo “foo”
default y

select 关键字

config A
Select B

表示如果这个配置项被选中,那么配置项B也会被选中

示例如下:

config DRM_RADEONtristate "ATI Radeon"depends on DRM && PCI && MMUselect FW_LOADERselect DRM_KMS_HELPERselect DRM_TTMselect POWER_SUPPLYselect HWMONselect BACKLIGHT_CLASS_DEVICEselect INTERVAL_TREEhelpChoose this option if you have an ATI Radeon graphics card.  Thereare both PCI and AGP versions.  You don't need to choose this torun the Radeon in plain VGA mode.If M is selected, the module will be called radeon.
表达式逻辑关系

depends on 关键字后面的表达式之间可以有逻辑关系,列举如下:

元素说明
等于<symbol> ‘=’ <symbol>
不等于<symbol> ‘!=’ <symbol>
赋值‘(’ <expr> ‘)’
逻辑非‘!’ <expr>
逻辑与<expr> ‘&&’ <expr>
Kconfig 其他语法

菜单结构
menu… endmenu
choices… endchoice

配置文件的编译

配置文件在经过Linux 系统编译后会生成一个头文件
autoconf.h

  • linux 路径:

include/generated

  • andoird 路径:

out/target/product/xxx/obj/KERNEL_OBJ/android-5.4/xxx/include/generated
内容如下:

.....c
#define CONFIG_IP6_NF_MATCH_AH_MODULE 1
#define CONFIG_NLS_CODEPAGE_861_MODULE 1
#define CONFIG_MTD_SPI_NAND_MODULE 1
#define CONFIG_RING_BUFFER 1
#define CONFIG_HARDENED_USERCOPY_FALLBACK 1
#define CONFIG_UWB_HWA_MODULE 1
#define CONFIG_SND_SOC_WM8804_MODULE 1
#define CONFIG_NF_CONNTRACK_H323_MODULE 1
#define CONFIG_HAVE_ARCH_SECCOMP_FILTER 1
#define CONFIG_IP6_NF_SECURITY_MODULE 1
#define CONFIG_SND_PROC_FS 1
#define CONFIG_VFIO_PCI_MMAP 1
.....

generated 中的文件还包括:

元素说明
compile.h编译主机信息
timeconst.h时间转换的固定宏
uapi/linux/version.h内核版本信息

Linux 内核引导方法

  1. 系统上电的时候,CPU会将PC指针赋值为一个特定的地址 0xFFFF0 并执行该地址的指令,在 PC 中该地址位于 BIOS 中,保存在主板的ROM 或者 Flash 中
  2. BIOS 按照CMOS设置定义的启动设备的顺序来搜索处于活动状态并且可以引导的设备,若是从硬盘启动,BIOS会将硬盘的 MBR(主引导记录)中的内容加载到RAM,MBR是一个512 字节的扇区,处于磁盘上的第一个扇区中(0道0柱面1扇区)。当MBR被加载到 RAM中之后,BIOS就会将控制权交给 MBR
  3. 主引导程序查找并且加载次引导加载程序,它在分区表中查找活动分区,将活动分区的引导记录从这个设备读入RAM并且启动它
  4. 次引导程序加载Linux 内核和可选的初始RAM磁盘,将控制权交给linux 内核代码
  5. 运行被加载的内核,并且启动用户空间的应用程序

Booloader 定义

  1. 可以在系统上电或者复位的时候以某种方法执行,
    执行方法包括:被BIOS引导执行,直接 NorFlash 执行,NAND Flash 代码被 MCU自动拷贝进入内部或者外部 RAM直接执行

  2. 能将U盘,磁盘,光盘,NAND/Nor Flash ROM SD卡中存储介质,甚至串口网口中的操作系统加载到 RAM,并且将控制权交给内核源代码执行

内核镜像不是完全直接可以执行的代码,而是一个压缩过的
zImage 小内核
bzImage big 大内核
但是不是 zImage 和 bzImage 中的一切都被压缩了,实际当中存在没有被压缩的部分,这部分中包含解压缩程序,解压缩程序会解压映像中被压缩的部分,zImage 和 bzImage 都是 gzip 压缩的,在这两个文件头部内嵌有gzip 解压缩代码.

Linux 内核C编程特点

Linux 内核编码风格

C++/windows 中习惯使用驼峰式命名法比如:
sendData
minValue

但是在Linux 中习惯使用下划线命名方法:
send_data
min_value

Linux 社区对编码规范的要求:

  • if/for/while/switch { 不另外起一行
  • if for 如果只有一行 不加{ }
  • 函数的 { } 都是要另外起一行
  • swicth 和 case 要对齐的
switch(suffix) {
case 'G':
break;
case 'W':
break;

Linux 代码规范的详细文档位于linux 代码中
http://androidxref.com/kernel_3.18/xref/Documentation/CodingStyle
可以使用:
scripts/checkpatch.pl 进行代码规范的检查

零长度数组和变量数组
struct data {
int a;
char data[0];
}

char data[0];不占用实际空间,但是通过 data[i] 可以访问 len 之后的 第index 个地址,并没有为data[] 分配内存 sizeof(struct data) == sizeof(int)

int n = 5;
char demo[n];
标号元素

GNUC 支持 case x…y 这样的写法

swicth(ch) {
case '0' ... '9':
break;
case 'a'
break;

GNUC 中,通过制定索引或者结构体成员名,允许初始化的值以任意的顺序出现,指定数组索引的方法是添加 [index] = ,当然也可以用[first … last]的形式制定一个范围

unsigned char data[MAX] = { [0...MAX-1] = 0 };

可以借助结构体成员名初始化结构体,Linux 2.6 推荐使用标准C的形式初始化结构体,就是在每个结构体成员的名称前加上一个点

可变参数宏

标准的C支持可变参数的函数,比如printf,在GNUC 中宏也可以接受可变数目的参数

#define pr_debug(fmt,arg...)    printk( fmt,##arg); )
##arg 表示的是零个或者多个参数的情况,这个参数以及参数之间的逗号构成了arg值
特殊属性声明

GNUC 允许声明函数,变量类型的特殊属性,如果要指定一个声明得到属性,在声明后面添加 attribute((ATTRIBUTE))
如果存在多个属性,句需要以逗号分隔,GNUC 支持的noreturn format section aligned packed 等十多个属性

type of关键字

type of关键字可以定义更加通用的宏 不需要预先知道变量的类型 类似于模板的作用

#define min(x,y) ({ /
const typeof(x) _x = (x);       /
const typeof(y) _y = (y);       /
(void) (&_x == &_y);            /
_x < _y ? _x : _y; })(void) (&_x == &_y); 的作用是检查这两个变量的类型是否一致。
内建函数

使用 gcc 编译的时候,如果使用 -ansi-pedanic 编译选项,则告诉GNC编译器不使用GNU扩展语法

do…while(0)

使用的优点:可以在宏之中使用,使相关的语句可以正确的展开
#define safe_free§ do{ free§; p = null; }while(0) (注意不需要使用逗号)
使用的时候,可以和函数一样的使用 safe_free§;

Arm 处理器工作模式

元素说明
用户模式(Usr)用于正常执行程序
快速中断模式(FIQ)用于高速数据传输
管理模式(svc)操作系统使用的保护模式,由系统调用执行软中断SWI命令触发
外部中断模式(IRQ)用于通常的中断处理
数据访问终止模式(abt)当数据或指令预取终止时进入该模式,可用于虚拟存储以及存储保护
系统模式(sys)运行具有特权的操作系统任务
未定义指令中止模式(und)当未定义的指令执行时进入该模式,可用于支持硬件

Arm的工作模式切换有两种方法:
被动切换:在arm运行的时候产生一些异常或者中断来自动进行模式切换
主动切换:通过软件改变,即软件设置寄存器来经行arm的模式切换,应为arm的工作模式都是可以通过相应寄存器的赋值来切换的

除了用户模式 其余6种模式被称为特权模式
特权模式中除了系统模式之外 其余5种模式称为异常模式

Linux 只能通过系统调用或者硬件中断完成用户模式到特权模式的组合

特权模式可访问任意系统资源,异常模式通常由系统异常状态切换进来

大多数程序运行于用户模式;进入特权模式是为了处理中断、异常、或者访问被保护的系统资源;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/79841.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常见汇编代码及其指令

1. 数据传输指令 1.1. mov 作用&#xff1a;将数据从源操作数复制到目标操作数。语法&#xff1a;mov dest, src mov eax, 10 ; 将立即数 10 存入 eax 寄存器 mov ebx, eax ; 将 eax 的值复制到 ebx mov [ecx], eax ; 将 eax 的值写入 ecx 指向的内存地址 1.2. …

STM32基础教程——软件SPI

目录 前言 技术实现 接线图 代码实现 技术要点 引脚操作 SPI初始化 SPI起始信号 SPI终止信号 SPI字节交换 宏替换命令 W25Q64写使能 忙等待 读取设备ID号和制造商ID 页写入 数据读取 实验结果 问题记录 前言 SPI&#xff08;Serial Peripheral Interf…

(B题|矿山数据处理问题)2025年第二十二届五一数学建模竞赛(五一杯/五一赛)解题思路|完整代码论文集合

我是Tina表姐&#xff0c;毕业于中国人民大学&#xff0c;对数学建模的热爱让我在这一领域深耕多年。我的建模思路已经帮助了百余位学习者和参赛者在数学建模的道路上取得了显著的进步和成就。现在&#xff0c;我将这份宝贵的经验和知识凝练成一份全面的解题思路与代码论文集合…

无网络环境下配置并运行 word2vec复现.py

需运行文件 # -*- coding: utf-8 -*- import torch import pandas as pd import jieba import torch import torch.nn as nn from tqdm import tqdm from torch.utils.data import DataLoader,Dataset from transformers import AutoTokenizer,AutoModeldef get_stop_word():w…

读《暗时间》有感

读《暗时间》有感 反思与笔记 这本书还是我无意中使用 ima 给我写职业规划的时候给出的&#xff0c;由于有收藏的习惯&#xff0c;我就去找了这本书。当读到第一章暗时间的时候给了我很大的冲击&#xff0c;我本身就是一个想快速读完一本书的人&#xff0c;看到东西没有深入思…

ubuntu安装Go SDK

# 下载最新版 Go 安装包&#xff08;以 1.21.5 为例&#xff09; wget https://golang.google.cn/dl/go1.21.5.linux-amd64.tar.gz # 解压到系统目录&#xff08;需要 root 权限&#xff09; sudo tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz # 使用 Go 官方安装脚本…

FFmpeg(7.1版本)编译生成ffplay

FFmpeg在编译的时候,没有生成ffplay,怎么办? 1. 按照上一篇文章:FFmpeg(7.1版本)在Ubuntu18.04上的编译_ffmpeg-7.1-CSDN博客 在build.sh脚本里配置了ffplay 但是,实际上却没有生成ffplay,会是什么原因呢? 2. 原因是编译ffplay的时候,需要一些依赖库 sudo apt-get i…

【Python 函数】

Python 中的函数&#xff08;Function&#xff09;是可重复使用的代码块&#xff0c;用于封装特定功能并提高代码复用性。以下是函数的核心知识点&#xff1a; 一、基础语法 1. 定义函数 def greet(name):"""打印问候语""" # 文档字符串&…

7. HTML 表格基础

表格是网页开发中最基础也最实用的元素之一,尽管现代前端开发中表格布局已被 CSS 布局方案取代,但在展示结构化数据时,表格依然发挥着不可替代的作用。本文将基于提供的代码素材,系统讲解 HTML 表格的核心概念与实用技巧。 一、表格的基本结构 一个完整的 HTML 表格由以下…

极狐GitLab 命名空间的类型有哪些?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 命名空间 命名空间在极狐GitLab 中组织项目。因为每一个命名空间都是单独的&#xff0c;您可以在多个命名空间中使用相同的项…

powershell批处理——io校验

powershell批处理——io校验 在刷题时&#xff0c;时常回想&#xff0c;OJ平台是如何校验竞赛队员提交的代码的&#xff0c;OJ平台并不看代码&#xff0c;而是使用“黑盒测试”&#xff0c;用测试数据来验证。对于每题&#xff0c;都事先设定了很多组输入数据&#xff08;data…

前端面经-webpack篇--定义、配置、构建流程、 Loader、Tree Shaking、懒加载与预加载、代码分割、 Plugin 机制

看完本篇你将基本了解webpack!!! 目录 一、Webpack 的作用 1、基本配置结构 2、配置项详解 1. entry —— 构建入口 2. output —— 输出配置 3. mode:模式设置 4. module:模块规则 5. plugins:插件机制 6. resolve:模块解析配置(可选) 7. devServer:开发服务器…

面试算法刷题练习1(核心+acm)

3. 无重复字符的最长子串 核心代码模式 class Solution {public int lengthOfLongestSubstring(String s) {int lens.length();int []numnew int[300];int ans0;for(int i0,j0;i<len;i){num[s.charAt(i)];while(num[s.charAt(i)]>1){num[s.charAt(j)]--;j;}ansMath.max…

拉削丝锥,螺纹类加工的选择之一

在我们的日常生活中&#xff0c;螺纹连接无处不在&#xff0c;从简单的螺丝钉到复杂的机械设备&#xff0c;都离不开螺纹的精密加工。今天&#xff0c;给大家介绍一种的螺纹刀具——拉削丝锥&#xff1a; 一、拉削丝锥的工作原理 拉削丝锥&#xff0c;听起来有点陌生吧&#…

数据清洗-电商双11美妆数据分析(二)

1.接下来用seaborn包给出每个店铺各个大类以及各个小类的销量销售额 先观察销量&#xff0c;各店小类中销量最高的是相宜本草的补水类商品以及妮维雅的清洁类商品&#xff0c;这两类销量很接近。而销售额上&#xff0c;相宜本草的补水类商品比妮维雅的清洁类商品要高得多&#…

【上位机——MFC】对话框

对话框的使用 1.添加对话框资源 2.定义一个自己的对话框类(CMyDlg)&#xff0c;管理对话框资源&#xff0c;派生自CDialog或CDialogEx均可 对话框架构 #include <afxwin.h> #include "resource.h"class CMyDlg :public CDialog {DECLARE_MESSAGE_MAP() publi…

2025东三省C题深圳杯C题数学建模挑战赛数模思路代码文章教学: 分布式能源接入配电网的风险分析

完整内容请看文章最下面的推广群 数据整理与分析 表1&#xff1a;有源配电网62节点系统负荷参数 内容&#xff1a;列出了62个节点的有功负荷&#xff08;单位&#xff1a;kW&#xff09;。 特点&#xff1a; 负荷范围&#xff1a;24 kW&#xff08;节点19&#xff09;到420 …

【人工智能】边缘计算技术及应用概述

边缘计算&#xff08;Edge Computing&#xff09;是一种分布式计算范式&#xff0c;其核心思想是将数据处理、存储和计算能力从传统的云端数据中心下沉到靠近数据源的边缘设备&#xff08;如传感器、摄像头、工业设备等&#xff09;或边缘服务器。这种架构旨在减少数据传输延迟…

FAISS(Facebook AI Similarity Search)

First steps with Faiss for k-nearest neighbor search in large search spaces - Davide’s GitHub pages FAISS&#xff08;Facebook AI Similarity Search&#xff09;是由Meta&#xff08;原Facebook&#xff09;AI团队开发的高效相似性搜索库&#xff0c;主要用于处理大规…

嵌入式开发学习日志Day15

一、指针指向字符型数组 &#xff08;1&#xff09;【const】&#xff1a;在指针变量中使用时&#xff0c;无法通过该指针修改被指向的变量&#xff1b; &#xff08;2&#xff09;【const】&#xff1a;关键字&#xff0c;在C和C中&#xff0c;能加就加&#xff0c;加了一定…