|
|
本篇关键词:、、、
|
|
|
|
|
|
[![](https://gitee.com/weharmonyos/resources/raw/master/index/08.png)](http://weharmonyos.com/blog/08.html)
|
|
|
|
|
|
|
|
|
[下载 >> 离线文档.鸿蒙内核源码分析(百篇博客分析.挖透鸿蒙内核).pdf](http://weharmonyos.com/resources/pdf/鸿蒙内核源码分析(百篇博客分析.挖透鸿蒙内核).zip)
|
|
|
|
|
|
基础知识相关篇为:
|
|
|
|
|
|
* [v01.12 鸿蒙内核源码分析(双向链表) | 谁是内核最重要结构体](http://weharmonyos.com/blog/01.html)
|
|
|
* [v02.01 鸿蒙内核源码分析(内核概念) | 名不正则言不顺](http://weharmonyos.com/blog/02.html)
|
|
|
* [v03.02 鸿蒙内核源码分析(源码结构) | 宏观尺度看内核结构](http://weharmonyos.com/blog/03.html)
|
|
|
* [v04.01 鸿蒙内核源码分析(地址空间) | 内核如何看待空间](http://weharmonyos.com/blog/04.html)
|
|
|
* [v05.03 鸿蒙内核源码分析(计时单位) | 内核如何看待时间](http://weharmonyos.com/blog/05.html)
|
|
|
* [v06.01 鸿蒙内核源码分析(宏的使用) | 为什么被翻译成了宏 ](http://weharmonyos.com/blog/06.html)
|
|
|
* [v07.01 鸿蒙内核源码分析(钩子框架) | 万物皆可HOOK ](http://weharmonyos.com/blog/07.html)
|
|
|
* [v08.04 鸿蒙内核源码分析(位图管理) | 一分钱被掰成八半使用](http://weharmonyos.com/blog/08.html)
|
|
|
* [v09.01 鸿蒙内核源码分析(POSIX) | 操作系统界的话事人 ](http://weharmonyos.com/blog/09.html)
|
|
|
* [v10.01 鸿蒙内核源码分析(main函数) | 要走了无数码农的第一次 ](http://weharmonyos.com/blog/10.html)
|
|
|
|
|
|
|
|
|
先看四个宏定义,进程和线程(线程就是任务)最高和最低优先级定义,`[0,31]`区间,即`32`级,优先级用于调度,`CPU`根据这个来决定先运行哪个进程和任务。
|
|
|
|
|
|
```c
|
|
|
#define OS_PROCESS_PRIORITY_HIGHEST 0 //进程最高优先级
|
|
|
#define OS_PROCESS_PRIORITY_LOWEST 31 //进程最低优先级
|
|
|
#define OS_TASK_PRIORITY_HIGHEST 0 //任务最高优先级,软时钟任务就是最高级任务,见于 OsSwtmrTaskCreate
|
|
|
#define OS_TASK_PRIORITY_LOWEST 31 //任务最低优先级
|
|
|
```
|
|
|
|
|
|
### 为何进程和线程都是32个优先级?
|
|
|
|
|
|
回答这个问题之前,先回答另一个问题,为什么人类几乎所有的文明都是用十进制的计数方式。答案掰手指就知道了,因为人有十根手指头。玛雅人的二十进制那是把脚指头算上了,但其实也算是十进制的表示。
|
|
|
|
|
|
这是否说明一个问题,认知受环境的影响,方向是怎么简单/方便怎么来。这也可以解释为什么人类语言发音包括各种方言对妈妈这个词都很类似,因为婴儿说mama是最容易的。 注意认识这点很重要!
|
|
|
|
|
|
而计算机的世界是二进制的,是是非非,清清楚楚,特别的简单,二进制已经最简单了,到底啦,不可能有更简单的了。还记得双向链表篇中说过的吗,因为简单所以才不简单啊,大道若简,计算机就靠着这01码,表述万千世界。
|
|
|
|
|
|
但人类的大脑不擅长存储,二进制太长了数到100就撑爆了大脑,记不住,为了记忆和运算方便,编程常用靠近10进制的 16进制来表示 ,0x9527ABCD 看着比 0011000111100101010100111舒服多了。
|
|
|
|
|
|
### 应用开发和内核开发有哪些区别?
|
|
|
|
|
|
区别还是很大的,这里只说一点,就是对位的控制能力,内核会出现大量的按位运算(&,|,~,^) , 一个变量的不同位表达不同的含义,但这在应用程序员那是很少看到的,他们用的更多的是逻辑运算(&&,||,!)
|
|
|
|
|
|
```c
|
|
|
#define OS_TASK_STATUS_INIT 0x0001U //初始化状态
|
|
|
#define OS_TASK_STATUS_READY 0x0002U //就绪状态的任务都将插入就绪队列
|
|
|
#define OS_TASK_STATUS_RUNNING 0x0004U //运行状态
|
|
|
#define OS_TASK_STATUS_SUSPEND 0x0008U //挂起状态
|
|
|
#define OS_TASK_STATUS_PEND 0x0010U //阻塞状态
|
|
|
```
|
|
|
|
|
|
这是任务各种状态(注者后续将比如成贴标签)表述,将它们还原成二进制就是:
|
|
|
|
|
|
0000000000000001 = 0x0001U
|
|
|
|
|
|
0000000000000010 = 0x0002U
|
|
|
|
|
|
0000000000000100 = 0x0004U
|
|
|
|
|
|
0000000000001000 = 0x0008U
|
|
|
|
|
|
0000000000010000 = 0x0010U
|
|
|
|
|
|
发现二进制这边的区别没有,用每一位来表示一种不同的状态,1表示是,0表示不是。
|
|
|
|
|
|
这样的好处有两点:
|
|
|
|
|
|
1.可以多种标签同时存在 比如 0x07 = 0b00000111,对应以上就是任务有三个标签(初始,就绪,和运行),进程和线程在运行期间是允许多种标签同时存在的。
|
|
|
|
|
|
2.节省了空间,一个变量就搞定了,如果是应用程序员要实现这三个标签同时存在,习惯上要定义三个变量的,因为你的排他性颗粒度是一个变量而不是一个位。
|
|
|
|
|
|
而对位的管理/运算就需要有个专门的管理器:位图管理器 (见源码 los_bitmap.c )
|
|
|
|
|
|
### 什么是位图管理器?
|
|
|
|
|
|
直接上部分代码,代码关键地方都加了中文注释,简单说就是对位的各种操作,比如如何在某个位上设1?如何找到最高位为1的是哪个位置?这些函数都是有大用途的。
|
|
|
|
|
|
```c
|
|
|
//对状态字的某一标志位进行置1操作
|
|
|
VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos)
|
|
|
{
|
|
|
if (bitmap == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
*bitmap |= 1U << (pos & OS_BITMAP_MASK);//在对应位上置1
|
|
|
}
|
|
|
//对状态字的某一标志位进行清0操作
|
|
|
VOID LOS_BitmapClr(UINT32 *bitmap, UINT16 pos)
|
|
|
{
|
|
|
if (bitmap == NULL) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
*bitmap &= ~(1U << (pos & OS_BITMAP_MASK));//在对应位上置0
|
|
|
}
|
|
|
/********************************************************
|
|
|
杂项算术指令
|
|
|
CLZ 用于计算操作数最高端0的个数,这条指令主要用于一下两个场合
|
|
|
计算操作数规范化(使其最高位为1)时需要左移的位数
|
|
|
确定一个优先级掩码中最高优先级
|
|
|
********************************************************/
|
|
|
//获取状态字中为1的最高位 例如: 00110110 返回 5
|
|
|
UINT16 LOS_HighBitGet(UINT32 bitmap)
|
|
|
{
|
|
|
if (bitmap == 0) {
|
|
|
return LOS_INVALID_BIT_INDEX;
|
|
|
}
|
|
|
|
|
|
return (OS_BITMAP_MASK - CLZ(bitmap));
|
|
|
}
|
|
|
//获取状态字中为1的最低位, 例如: 00110110 返回 2
|
|
|
UINT16 LOS_LowBitGet(UINT32 bitmap)
|
|
|
{
|
|
|
if (bitmap == 0) {
|
|
|
return LOS_INVALID_BIT_INDEX;
|
|
|
}
|
|
|
|
|
|
return CTZ(bitmap);//
|
|
|
}
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
### 位图在哪些地方应用?
|
|
|
|
|
|
内核很多模块在使用位图,这里只说进程和线程模块,还记得开始的问题吗,为何进程和线程都是32个优先级?因为他们的优先级是由位图管理的,管理一个UINT32的变量,所以是32级,一个位一个级别,最高位优先级最低。
|
|
|
|
|
|
```c
|
|
|
UINT32 priBitMap; /**< BitMap for recording the change of task priority, //任务在执行过程中优先级会经常变化,这个变量用来记录所有曾经变化
|
|
|
the priority can not be greater than 31 */ //过的优先级,例如 ..01001011 曾经有过 0,1,3,6 优先级
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
这是任务控制块中对调度优先级位图的定义,注意一个任务的优先级在运行过程中可不是一成不变的,内核会根据运行情况而改变它的,这个变量是用来保存这个任务曾经有过的所有优先级历史记录。
|
|
|
|
|
|
比如 任务A的优先级位图是 00000001001011 ,可以看出它曾经有过四个调度等级记录,那如果想知道优先级最低的记录是多少时怎么办呢?
|
|
|
|
|
|
诶,上面的位图管理器函数 UINT16 LOS_HighBitGet(UINT32 bitmap) 就很有用啦 ,它返回的是1在高位出现的位置,可以数一下是 6
|
|
|
|
|
|
因为任务的优先级0最大,所以最终的意思就是A任务曾经有过的最低优先级是6
|
|
|
|
|
|
一定要理解位图的操作,内核中大量存在这类代码,尤其到了汇编层,对寄存器的操作大量的出现。
|
|
|
|
|
|
比如以下这段汇编代码。
|
|
|
|
|
|
```c
|
|
|
MSR CPSR_c, #(CPSR_INT_DISABLE | CPSR_SVC_MODE) @禁止中断并切到管理模式
|
|
|
LDRH R1, [R0, #4] @将存储器地址为R0+4 的低16位数据读入寄存器R1,并将R1的高16 位清零
|
|
|
ORR R1, #OS_TASK_STATUS_RUNNING @或指令 R1=R1|OS_TASK_STATUS_RUNNING
|
|
|
STRH R1, [R0, #4] @将寄存器R1中的低16位写入以R0+4为地址的存储器中
|
|
|
|
|
|
|
|
|
```
|
|
|
### **编程实例**
|
|
|
|
|
|
对数据实现位操作,本实例实现如下功能:
|
|
|
|
|
|
* 某一标志位置1。
|
|
|
* 获取标志位为1的最高bit位。
|
|
|
* 某一标志位清0。
|
|
|
* 获取标志位为1的最低bit位。
|
|
|
|
|
|
```c
|
|
|
#include "los_bitmap.h"
|
|
|
#include "los_printf.h"
|
|
|
|
|
|
static UINT32 Bit_Sample(VOID)
|
|
|
{
|
|
|
UINT32 flag = 0x10101010;
|
|
|
UINT16 pos;
|
|
|
|
|
|
dprintf("\nBitmap Sample!\n");
|
|
|
dprintf("The flag is 0x%8x\n", flag);
|
|
|
|
|
|
pos = 8;
|
|
|
LOS_BitmapSet(&flag, pos);
|
|
|
dprintf("LOS_BitmapSet:\t pos : %d, the flag is 0x%0+8x\n", pos, flag);
|
|
|
|
|
|
pos = LOS_HighBitGet(flag);
|
|
|
dprintf("LOS_HighBitGet:\t The highest one bit is %d, the flag is 0x%0+8x\n", pos, flag);
|
|
|
|
|
|
LOS_BitmapClr(&flag, pos);
|
|
|
dprintf("LOS_BitmapClr:\t pos : %d, the flag is 0x%0+8x\n", pos, flag);
|
|
|
|
|
|
pos = LOS_LowBitGet(flag);
|
|
|
dprintf("LOS_LowBitGet:\t The lowest one bit is %d, the flag is 0x%0+8x\n\n", pos, flag);
|
|
|
|
|
|
return LOS_OK;
|
|
|
}
|
|
|
```
|
|
|
### **结果验证**
|
|
|
```c
|
|
|
Bitmap Sample!
|
|
|
The flag is 0x10101010
|
|
|
LOS_BitmapSet: pos : 8, the flag is 0x10101110
|
|
|
LOS_HighBitGet:The highest one bit is 28, the flag is 0x10101110
|
|
|
LOS_BitmapClr: pos : 28, the flag is 0x00101110
|
|
|
LOS_LowBitGet: The lowest one bit is 4, the flag is 0x00101110
|
|
|
```
|
|
|
|
|
|
### 百文说内核 | 抓住主脉络
|
|
|
|
|
|
* 百文相当于摸出内核的肌肉和器官系统,让人开始丰满有立体感,因是直接从注释源码起步,在加注释过程中,每每有心得处就整理,慢慢形成了以下文章。内容立足源码,常以生活场景打比方尽可能多的将内核知识点置入某种场景,具有画面感,容易理解记忆。说别人能听得懂的话很重要! 百篇博客绝不是百度教条式的在说一堆诘屈聱牙的概念,那没什么意思。更希望让内核变得栩栩如生,倍感亲切。
|
|
|
* 与代码需不断`debug`一样,文章内容会存在不少错漏之处,请多包涵,但会反复修正,持续更新,`v**.xx` 代表文章序号和修改的次数,精雕细琢,言简意赅,力求打造精品内容。
|
|
|
* 百文在 < 鸿蒙研究站 | 开源中国 | 博客园 | 51cto | csdn | 知乎 | 掘金 > 站点发布,**鸿蒙研究站 | weharmonyos** 中回复 **百文** 可方便阅读。
|
|
|
* ![](https://gitee.com/weharmonyos/resources/raw/master/common/cate.png)
|
|
|
|
|
|
按功能模块:
|
|
|
|
|
|
* 基础知识 >> [双向链表](http://weharmonyos.com/blog/01.html) | [内核概念](http://weharmonyos.com/blog/02.html) | [源码结构](http://weharmonyos.com/blog/03.html) | [地址空间](http://weharmonyos.com/blog/04.html) | [计时单位](http://weharmonyos.com/blog/05.html) | [宏的使用](http://weharmonyos.com/blog/06.html) | [钩子框架](http://weharmonyos.com/blog/07.html) | [位图管理](http://weharmonyos.com/blog/08.html) | [POSIX](http://weharmonyos.com/blog/09.html) | [main函数](http://weharmonyos.com/blog/10.html) |
|
|
|
* 进程管理 >> [调度故事](http://weharmonyos.com/blog/11.html) | [进程控制块](http://weharmonyos.com/blog/12.html) | [进程空间](http://weharmonyos.com/blog/13.html) | [线性区](http://weharmonyos.com/blog/14.html) | [红黑树](http://weharmonyos.com/blog/15.html) | [进程管理](http://weharmonyos.com/blog/16.html) | [Fork进程](http://weharmonyos.com/blog/17.html) | [进程回收](http://weharmonyos.com/blog/18.html) | [Shell编辑](http://weharmonyos.com/blog/19.html) | [Shell解析](http://weharmonyos.com/blog/20.html) |
|
|
|
* 任务管理 >> [任务控制块](http://weharmonyos.com/blog/21.html) | [并发并行](http://weharmonyos.com/blog/22.html) | [就绪队列](http://weharmonyos.com/blog/23.html) | [调度机制](http://weharmonyos.com/blog/24.html) | [任务管理](http://weharmonyos.com/blog/25.html) | [用栈方式](http://weharmonyos.com/blog/26.html) | [软件定时器](http://weharmonyos.com/blog/27.html) | [控制台](http://weharmonyos.com/blog/28.html) | [远程登录](http://weharmonyos.com/blog/29.html) | [协议栈](http://weharmonyos.com/blog/30.html) |
|
|
|
* 内存管理 >> [内存规则](http://weharmonyos.com/blog/31.html) | [物理内存](http://weharmonyos.com/blog/32.html) | [虚拟内存](http://weharmonyos.com/blog/33.html) | [虚实映射](http://weharmonyos.com/blog/34.html) | [页表管理](http://weharmonyos.com/blog/35.html) | [静态分配](http://weharmonyos.com/blog/36.html) | [TLFS算法](http://weharmonyos.com/blog/37.html) | [内存池管理](http://weharmonyos.com/blog/38.html) | [原子操作](http://weharmonyos.com/blog/39.html) | [圆整对齐](http://weharmonyos.com/blog/40.html) |
|
|
|
* 通讯机制 >> [通讯总览](http://weharmonyos.com/blog/41.html) | [自旋锁](http://weharmonyos.com/blog/42.html) | [互斥锁](http://weharmonyos.com/blog/43.html) | [快锁使用](http://weharmonyos.com/blog/44.html) | [快锁实现](http://weharmonyos.com/blog/45.html) | [读写锁](http://weharmonyos.com/blog/46.html) | [信号量](http://weharmonyos.com/blog/47.html) | [事件机制](http://weharmonyos.com/blog/48.html) | [信号生产](http://weharmonyos.com/blog/49.html) | [信号消费](http://weharmonyos.com/blog/50.html) | [消息队列](http://weharmonyos.com/blog/51.html) | [消息封装](http://weharmonyos.com/blog/52.html) | [消息映射](http://weharmonyos.com/blog/53.html) | [共享内存](http://weharmonyos.com/blog/54.html) |
|
|
|
* 文件系统 >> [文件概念](http://weharmonyos.com/blog/55.html) | [文件故事](http://weharmonyos.com/blog/56.html) | [索引节点](http://weharmonyos.com/blog/57.html) | [VFS](http://weharmonyos.com/blog/58.html) | [文件句柄](http://weharmonyos.com/blog/59.html) | [根文件系统](http://weharmonyos.com/blog/60.html) | [挂载机制](http://weharmonyos.com/blog/61.html) | [管道文件](http://weharmonyos.com/blog/62.html) | [文件映射](http://weharmonyos.com/blog/63.html) | [写时拷贝](http://weharmonyos.com/blog/64.html) |
|
|
|
* 硬件架构 >> [芯片模式](http://weharmonyos.com/blog/65.html) | [ARM架构](http://weharmonyos.com/blog/66.html) | [指令集](http://weharmonyos.com/blog/67.html) | [协处理器](http://weharmonyos.com/blog/68.html) | [工作模式](http://weharmonyos.com/blog/69.html) | [寄存器](http://weharmonyos.com/blog/70.html) | [多核管理](http://weharmonyos.com/blog/71.html) | [中断概念](http://weharmonyos.com/blog/72.html) | [中断管理](http://weharmonyos.com/blog/73.html) |
|
|
|
* 内核汇编 >> [编码方式](http://weharmonyos.com/blog/74.html) | [汇编基础](http://weharmonyos.com/blog/75.html) | [汇编传参](http://weharmonyos.com/blog/76.html) | [可变参数](http://weharmonyos.com/blog/77.html) | [开机启动](http://weharmonyos.com/blog/78.html) | [进程切换](http://weharmonyos.com/blog/79.html) | [任务切换](http://weharmonyos.com/blog/80.html) | [中断切换](http://weharmonyos.com/blog/81.html) | [异常接管](http://weharmonyos.com/blog/82.html) | [缺页中断](http://weharmonyos.com/blog/83.html) |
|
|
|
* 编译运行 >> [编译过程](http://weharmonyos.com/blog/84.html) | [编译构建](http://weharmonyos.com/blog/85.html) | [GN语法](http://weharmonyos.com/blog/86.html) | [忍者无敌](http://weharmonyos.com/blog/87.html) | [ELF格式](http://weharmonyos.com/blog/88.html) | [ELF解析](http://weharmonyos.com/blog/89.html) | [静态链接](http://weharmonyos.com/blog/90.html) | [重定位](http://weharmonyos.com/blog/91.html) | [动态链接](http://weharmonyos.com/blog/92.html) | [进程映像](http://weharmonyos.com/blog/93.html) | [应用启动](http://weharmonyos.com/blog/94.html) | [系统调用](http://weharmonyos.com/blog/95.html) | [VDSO](http://weharmonyos.com/blog/96.html) |
|
|
|
* 调测工具 >> [模块监控](http://weharmonyos.com/blog/97.html) | [日志跟踪](http://weharmonyos.com/blog/98.html) | [系统安全](http://weharmonyos.com/blog/99.html) | [测试用例](http://weharmonyos.com/blog/100.html) |
|
|
|
* 前因后果 >> [总目录](http://weharmonyos.com/blog/101.html) | [源码注释](http://weharmonyos.com/blog/102.html) | [静态站点](http://weharmonyos.com/blog/103.html) | [参考手册](http://weharmonyos.com/blog/104.html) |
|
|
|
|
|
|
### 百万注源码 | 处处扣细节
|
|
|
|
|
|
* 百万汉字注解内核目的是要看清楚其毛细血管,细胞结构,等于在拿放大镜看内核。内核并不神秘,带着问题去源码中找答案是很容易上瘾的,你会发现很多文章对一些问题的解读是错误的,或者说不深刻难以自圆其说,你会慢慢形成自己新的解读,而新的解读又会碰到新的问题,如此层层递进,滚滚向前,拿着放大镜根本不愿意放手。
|
|
|
* [< gitee](https://gitee.com/weharmony/kernel_liteos_a_note) | [github](https://github.com/kuangyufei/kernel_liteos_a_note) | [coding](https://weharmony.coding.net/public/harmony/kernel_liteos_a_note/git/files) | [gitcode >](https://gitcode.net/kuangyufei/kernel_liteos_a_note) 四大码仓推送 | 同步官方源码,**鸿蒙研究站 | weharmonyos** 中回复 **百万** 可方便阅读。
|
|
|
|
|
|
[![](https://gitee.com/weharmony/kernel_liteos_a_note/widgets/widget_card.svg?colors=393222,ebdfc1,fffae5,d8ca9f,393222,a28b40)](https://gitee.com/weharmony/kernel_liteos_a_note)
|
|
|
### 关注不迷路 | 代码即人生
|
|
|
|
|
|
![](https://gitee.com/weharmonyos/resources/raw/master/common/so1so.png)
|
|
|
|
|
|
据说喜欢点赞分享的,后来都成了大神。:)
|
|
|
|
|
|
|