-
指令是稳定的,但指令序列是变化的,只有这样计算机才能够实现用计算来解决一切问题这个目标。计算是稳定的,但计算的数据是多变的,多态的,地址是数据,控制信号也是数据.指令集本身也是数据(固定的数据).只有这样才能够让计算机不必修改基础架构却可以适应不断发展变化的技术革命。
-
cpu
是负责执行指令的,谁能给它指令?是线程(也叫任务), 任务是内核的调度单元,调度到哪个任务CPU就去执行哪个任务的指令. 要执行指令就要有个取指令的开始地址. 开始地址就是大家所熟知的main函数.一个程序被加载解析后内核会在ELF中找到main函数的位置,并自动创建一个线程,指定线程的入口地址为main函数的地址,由此开始了取指,译指,执指之路. -
多线程内核是怎么处理的? 一样的, 以JAVA举例,对内核来说 new thread中的run() 函数 和 main() 并没有区别. 都是一个线程(任务)的执行入口. 注意在系列篇中反复的说任务就是线程,线程就是任务,它们是一个东西在不同层面上的描述.对应用层说线程,对内核层说任务. 有多少个线程就会有多少个入口,它们统一接受调度算法的调度, 调度算法只认优先级的高低,不会管你是main() 还是 run() 而区别对待.
-
定时器的实现也是通过任务实现的,只不过是个系统任务
OsSwtmrTaskCreate
,优先级最高,和入口地址OsSwtmrTask
由系统指定. -
所以理解CPU就要先理解任务,任务是理解内核的主线,把它搞明白了分析内核就轻轻松松,事半功倍了.看似高深的CPU只不过是搂草打兔子.不相信?那就看看内核对CPU是怎么描述的吧.本篇就围绕这个结构体展开说.
Percpu
percpu变量,顾名思义,就是对于同一个变量,每个cpu都有自己的一份,它可以被用来存放一些cpu独有的数据,比如cpu的id,cpu上正在运行的任务等等.
Percpu g_percpu[LOSCFG_KERNEL_CORE_NUM];//CPU核描述符,描述每个CPU的信息.
typedef struct {//内核对cpu的描述
SortLinkAttribute taskSortLink; /* task sort link */ //挂等待和延时的任务
SortLinkAttribute swtmrSortLink; /* swtmr sort link */ //挂定时器
UINT32 idleTaskID; /* idle task id */ //空闲任务ID 见于 OsIdleTaskCreate
UINT32 taskLockCnt; /* task lock flag */ //任务锁的数量,当 > 0 的时候,需要重新调度了
UINT32 swtmrHandlerQueue; /* software timer timeout queue id */ //软时钟超时队列句柄
UINT32 swtmrTaskID; /* software timer task id */ //软时钟任务ID
UINT32 schedFlag; /* pending scheduler flag */ //调度标识 INT_NO_RESCH INT_PEND_RESCH
#if (LOSCFG_KERNEL_SMP == YES)
UINT32 excFlag; /* cpu halt or exc flag */ //CPU处于停止或运行的标识
#endif
} Percpu;
至于 g_percpu
的值怎么来的,因和编译过程相关,将在后续编译篇中说明.
Percpu
结构体不复杂,但很重要,一个一个掰开了说.
-
taskSortLink
是干什么用的? 一个任务在运行过程中,经常会主动或被动停止,而进入等待状态.-
主动停止情况, 例如:主动delay300毫秒,这是应用层很常见的操作.
-
被动停止情况, 例如:申请互斥锁失败,等待某个事件发生.
发生这些情况时任务将被挂到taskSortLink
上.这些任务可能来自不同的进程,但都是因为在被这
-