从linux和ucos的比较中来看进程这个概念
这种问题就要和ucos结合起来嘛。
程序和进程:
程序:存放在磁盘上的一些列代码和数据的可执行映像,是一个静止的实体。
进程:是一个执行中的程序,它是动态的实体。
linux进程的四要素:
1. 有一段程序供其执行。这段程序不一定是某个进程所专有,可以与其他进程共用。
2. 有进程专用的内核空间堆栈。
3. 在内核中有一个task_struct数据结构,即通常所说的“进程控制块”。有了这个数据结构,进程才能成为内核调度的一个基本单位接受内核的调度。
4. 有独立的用户空间。
注:下图是根据用户控件去区分进程,用户线程,内核线程。
进程状态:
Ucos:
一个ucos进程有标准的三个状态:
Linux:
Linux的状态在基本的状态上又增加了几个:
1. TASK_RUNNING:进程正在被CPU执行,或者已经准备就绪,随时可以执行。当一个进程刚被创建时,就处于TASK_RUNNING状态。
2. TASK_INTERRUPTIBLE:处于等待中的进程,待等待条件为真时被唤醒,也可被信号或者中断唤醒。
3. TASK_UNINTERRUPTIBLE:处于等待中的进程,待资源有效时被唤醒,但不可以由其他进程通过信号或中断唤醒。
4. TASK_KILLABLE:linux2.6.25新引入的进程睡眠状态,原理类似于TASK_UNINTERRUPTIBLE,但是可以被致命信号(SIGKILL)唤醒。
5. TASK_TRACED:正处于被调试状态的进程。
6. TASK_DEAD:进程退出时(调用do_exit),所处的状态。
任务控制块:
Ucos:
通过os_tcb来控制任务状态。比较重要的数据结构有:指向任务堆栈栈顶的指针,OS_TCB双向链表的前后链接的指针,指向事件控制块的指针,指向邮箱的指针,指向事件标志节点的指针,就绪态标志,延时剩余节拍记录,任务状态字,任务优先级等等。
Linux:
Linux的进程,线程都使用task_struct来表示,他包含了大量进程/线程的信息,其中比较重要的有:
Pid_t pid; //进程号
Long state; //进程状态
Int prio; //进程优先级
而在ucosii里,优先级就是进程的id了,最多有64个任务,最多有64个优先级,每两个任务的优先级都不相同。
调度策略:
Ucos:
ucos不支持时间片轮番调度法,应用程序中各任务优先级不能相同。
Linux:
先说一下普通进程优先级和实时进程优先级:进程提供了两种优先级,一种是普通的进程优先级,第二个是实时优先级。前者适用SCHED_NORMAL调度策略,后者可选SCHED_FIFO或SCHED_RR调度策略。任何时候,实时进程的优先级都高于普通进程,实时进程只会被更高级的实时进程抢占,同级实时进程之间是按照FIFO(一次机会做完)或者RR(多次轮转)规则调度的。
Linux几种常见的调度策略:
vSCHED_NORMAL(SCHED_OTHER):普通的分时进程
vSCHED_FIFO :先入先出的实时进程
vSCHED_RR:时间片轮转的实时进程
vSCHED_BATCH:批处理进程
vSCHED_IDLE: 只在系统空闲时才能够被调度执行的进程
调度时机:
Ucos:
1. 中断返回。
2. 申请不到资源主动挂起。
3. 释放一个资源,比如信号量。
4. 主动时延。
注意:超时而继续的进程不会再次任务调度了,因为超时之后会进入就绪态,当它转换为运行态的时候就已经证明它是优先级最高而得到调度的了。
Ucos的任务调度可能会陷入优先级反转,高优先级任务的优先级会被拉低到占用资源的优先级,解决方式为提升占用资源任务的优先级,如果内核自动改变任务的优先级就叫优先级继承,ucos没有优先级继承的功能。
Linux:
Linux的抢占分为用户抢占和内核抢占。
用户抢占发生在:
1. 从系统调用返回用户空间。
2. 从中断处理程序返回用户空间。
内核抢占发生在:
1. 中断处理程序完成,返回内核空间之前。
2. 党内和代码再一次具有可抢占性的时候,如解锁及使能软中断等。
下列时机不允许发生抢占:
1. 内核正在运行中断处理。
2. 内核正在进行中断上线文的bottom half(中断的底半部)处理,硬件终端返回前会执行软中断,此时仍然处于中断上下文中。
3. 进程正持有spinlock自旋锁、writelock/readlock读写锁等,当持有这些锁时,不应该被抢占,否则由于抢占将可能导致其他进程长期得不到锁,而让系统处于死锁状态。
4. 内核正在执行调度程序Scheduler。抢占的原因就是为了进行新的调度,没有理由将调度程序抢占掉再运行调度程序。
调度步骤:
Ucos:
1. 保存当前寄存器。
2. 在当前任务控制块中保存当前任务的堆栈指针。
3. 寻找到最高优先级的任务。
4. 从新任务的堆栈恢复处理器所有寄存器的值。
Linux:
Schedule函数工作流程如下:
1). 清理当前运行中的进程;
2). 选择下一个要运行的进程;
3). 设置新进程的运行环境;
4). 进程上下文切换。