#include”config.h”
#ifndef __OS_H_H_H_H_
#define __OS_H_H_H_H_

本人正在写一个用于单片机嵌入式系统的轻型操作系统,主要用于资源比较匮乏的8位机,16位机和arm的低端产品。目前刚刚起步希望各位大侠可以多多指教,也希望能有人一起合作,虽然进度会很慢,甚至有时会停止但是我不会放弃。

#include”config.h”
#include”os.h”
#include”core.h”
#include”cpu.h”

/*–0—1—2—3—4—5—6—7–*/
        

轻型操作系统的描述文档:(其中一部分,其他的会不断写完,只是我的业余做的,更新会很慢)

/********************************************************************************
函数名字:PID gethighrdypid(_OS_PRDYTLBINDEX index)
传入参数:_OS_PRDYTLBINDEX 见os.h文件,用于索引最高就绪优先级的PID
返回参数:PID 见os.h文件,进程的ID
功能描述:从进程就绪表中处于就绪态的优先级最高的进程。
注意事项:由于系统有一个永远处于就绪态的进程,所以index必不可能为零,所以到最后不用
进行零的判别;
********************************************************************************/
PID gethighrdypid(_OS_PRDYTLBINDEX index)
{
#if OS_THEORY_PROCESS_COUNT==8
    return
(PID)_os_prdytlb[index];
#endif

//内核管理控制块的结构定义
typedef struct OSCB{
PCB*pcur;             //指向当前运行的进程控制块的指针;
PCB*pfirst;           //指向第一个进程控制块的指针;
PCB*plast;            //指向最后一个进程控制块的指针;
INT16U _int_nest;     //中断嵌套层次;
PSTK**pstktlb;        //指向进程指针数组的指针;
_OS_PRDYTLB*pprdytlb; //指向进程就绪表的指针;
PID highpriorpid;     //处于高优先度的pid
}_OS_OSCB;

此文件是OS.c的文档文件
/*****************************************************************************************************
名词解析:
PCB: (process control block) 
进程控制块(管理进程的数据结构)———见os.h文件 
MCB: (memory  control block) 
内存控制块(管理内存的数据结构)———见os.h文件
QCB: (queue   control block) 
队列控制块(管理消息队列的数据结构)—–见os.h文件
澳门新葡萄京官网注册 ,ECB: (event   control block) 
事件控制块(管理事件的数据结构)———见os.h文件
SCB: (semaphore control block)
信号量控制块(管理信号量的数据结构)—-见os.h文件
OSCB: (operator system control block)
内核控制块(管理内核的数据结构)-见os.h文件

#if
OS_THEORY_PROCESS_COUNT==16
    if((index&0x00FF)!=0)
    {
        index&=0x00FF;
        return
(PID)_os_prdytlb[index];
    }
    else
    {
        index>>=8;
        index&=0x00FF;
        return
(PID)(_os_prdytlb[index]+8);
    }
#endif

//进程管理控制块的结构定义
typedef struct PCB{
    PSTK *pstk;          //进程堆栈指针
    PID  pid;            //进程号;
    PPC  *ppc;           //进程PC指针(只是指向代码开始位置)
    PCB  *pfather;       //父进程进程快指针;
    PSTA state;          //进程状态;
    //PCB  *pback;         //指向下一个pcb块
    //PCB  *pfront;        //指向前一个pcb块
    //OSCB *oscb;          //指向内核控制块的指针;

PSTK :   (process stack pointer)    进程的堆栈指针寄存器;
PID :    (process ID)    进程的身份证号;
PSTA:    (process state) 进程的状态;
PNAM:    (process name)  进程名称
PSTKTLB: (process  stack pointer table) 进程堆栈针数组表;
PPC :    (process PC )    进程的代码指针寄存器;
_OS_PRDYTLB:               (oprator system process ready table)
操作系统进程就绪表
OS_THEORY_PROCESS_COUNT:  
内核支持的理论上的最大进程数;此数应为8、16、32、64、128、256…中的一个
OS_REALITY_PROCESS_COUNT:  内核实际上拥有的初始进程数;
OS_REALITY_PROCESS_MAX_COUNT: 内核实际上拥有的可支配的最大进程数
/*****************************************************************************************************
进程状态说明:
1、执行态(run)    该进程正在被cpu执行
2、就绪态(ready)  该进程已经准备好了,等待cpu的执行
3、等待态(wait)  
该进程正等待某个事件的发生,若是发生硬件错误将会被内核杀死
4、死亡态(dead)  
该进程被内核杀死,或者被父进程杀死,除非被复活,否则无法获取cpu时间
//5、调试态(debug)  该进程正在调试,此时可以进行特权操作

#if
OS_THEORY_PROCESS_COUNT==32

#if P_NAME_EN ==1
    PNAME*pname;     //指向进程名的数据结构的指针;
#endif

/*****************************************************************************************************
进程状态切换原则:
从执行态可以进入(除了调试态外)其他任何状态;
从就绪态可以进入(除了调试态外)其他任何状态;
从等待态只能进入就绪态和死亡态
从死亡态只能进入就绪态或者等待态
PID小的进程为优先权较高的进程,PID=0的进程为优先权最高的进程;
进程调度种类:
1、高优先级进程自杀或者高优先级进程自动放弃cpu控制权,即调用wait()函数,等待某个事件的发生;
2、低优先级的进程被高优先级的进程打断,即某事件的发生,即调用了send()函数,或者中断发生了。
说明图表:                                         | |
                                                 |     |
                                     |———->|dead
|<———-| 
                                     |           |     |——–|  |
                                     |             | |          |  |
                                     |            /|  |        |  |
                                     |             |  |/       |  |
                                    | |            | | |        |  |
                                  |     |        |       |      |  |
                                  | run | ——>| ready |      | 
|
                                  |     | <——|       |      | 
|
                                    | |            | | |        |  |
                                     |            /|  |        |  |
                                     |             |   |        |  |
                                     |             |  |/       |  |
                                     |              | |         |  |
             |            |     |<——|  |
             |———–>| wait|———-|
                          |     |
                            | |

    if((index&0x000000FF)!=0)
    {
        index&=0x000000FF;
        return
(PID)_os_prdytlb[index];
    }
    else if((index&0x0000FF00)!=0)
    {
        index>>=8;
        index&=0x000000FF;
        return
(PID)(_os_prdytlb[index]+8);
    }
    else if((index&0x00FF0000)!=0)
    {
        index>>=16;
        index&=0x000000FF;
        return
(PID)(_os_prdytlb[index]+16);
    }
    else
    {
        index>>=24;
        index&=0x000000FF;
        return
(PID)(_os_prdytlb[index]+24);
    }
#endif
}

#if MEMORY_EN==1
    MCB*pmcb;        //指向内存管理控制块的指针;
#endif

/*****************************************************************************************************
进程调度的数据结构:

/*******************************************************************************
函数名字:void _os_schedul(void)
传入参数:没有
返回参数:没有
功能描述:内核进行一次普通进程调度,将最合理的进程装入cpu物理区间
底层调用: PID gethighrdypid(_OS_PRDYTLBINDEX index)(本文件)
          void _os_context();
********************************************************************************/
void _os_schedul(void)
{
    _os_oscb.pcur->state=PSTATE_WAITE;       /*将当前进程置为等待;*/
    _os_oscb.gethighrdypid=(_os_prdytlbindex);
    _os_oscb.pcur=_os_oscb.pfirst+_os_oscb.highpriorpid;
    _os_context();   /*进行cpu上下文切换,见cpu.c文件*/
    return;
}

#if SEMAPHORE_EN==1  
    SCB*pscb;        //指向信号量管理控制块的指针;
#endif

原则:调度越快越好,实时性越高越好,采用优先权的调度策略。

/********************************************************************************
函数名字:void _os_intschedul(void)
传入参数:没有
返回参数:没有
功能描述:在中断的情况下内核进行一次进程调度,将最合理的进程装入cpu物理区间
注意事项:只能用在中断的情况下进行的调度;
底层调用: PID gethighrdypid(_OS_PRDYTLBINDEX index)(本文件)
          void _os_intcontext();
********************************************************************************/
void _os_intschedul(void)
{
    _os_oscb.pcur->state=PSTATE_WAITE;       /*将当前进程置为等待;*/
    _os_oscb.gethighrdypid=(_os_prdytlbindex);
    _os_oscb.pcur=_os_oscb.pfirst+_os_oscb.highpriorpid;
    _os_intcontext();   /*进行cpu上下文切换,见cpu.c文件*/
    return;
}

#if EVENT_EN==1
    ECB*pecb;       //指向事件管理控制块的指针;
#endif

目标:设计底线至少可以有16个进程同时运行,调度时间最坏时间不超过1ms;

/********************************************************************************
函数名字:void _os_killschedul(void)
传入参数:没有
返回参数:没有
功能描述:在进程自杀或者被杀的情况下内核进行一次进程调度
底层调用: PID gethighrdypid(_OS_PRDYTLBINDEX index)(本文件)
          void _os_context();
********************************************************************************/
void _os_killschedul(void)
{
    _os_oscb.pcur->state=PSTATE_WAITE;       /*将当前进程置为等待;*/
    _os_oscb.gethighrdypid=(_os_prdytlbindex);
    _os_oscb.pcur=_os_oscb.pfirst+_os_oscb.highpriorpid;
    _os_context();   /*进行cpu上下文切换,见cpu.c文件*/
    return;
}

} _OS_PCB;

调度过程步骤:
1、获取当前处于就绪态的最高优先权的进程的PID;
2、通过PID获取该进程的PCB结构的指针;(各进程的PCB指针存放在表格PSTKTLB里面)
3、通过PCB指针找到当前进程的堆栈指针;
4、从该进程的堆栈中将其cpu上下文调度出来;
5、进行cpu上下文切换;
6、将cpu控制权交给当前进程;

core.h未完待续

//OS全局变量总集
_OS_OSCB _os_oscb;//内核控制块;
_OS_PCB  _os_pcb[OS_REALITY_PROCESS_COUNT+2];//创建进程控制块的数组,由于有两个系统进程所以要加2;

最主要的问题:
1、如何快速地找到处于就绪态的最高优先权的进程的PID;
2、是问题一得衍生问题,就是如何将一个从其他状态的进程进入就绪态时如果快速地插入有序的列表中进程;
3、如何进行cpu上下文切换;
4、如何保证整个切换过程时间的大小不因进程的增多而急剧增大,即怎样保持实时性;
/*****************************************************************************************************
方案一、
1、设计一个数组,数组大小和进程的个数相等,数组的索引号刚好和PID相同,数组的元素为指向各个进程控制块的
指针;这样可以通过PID来取出进程的控制块;
2、设计一个有序队列,此队列用于存放处于就绪态的进程队列,使取进程时直接从队列首取出即为优先权最高的进
程;(还可以将进程的控制快指针和PID同放于此队列那将快)
方案二、
1、设计一个整型的无符号数组,每个数组的元素的每位对应一个PID,该位为1时,表明对应的PID的进程处于将就绪
态,而为0时表明处于非就绪态;
而数组的大小和数组的元素的位数可以灵活设定,这样就可以用折半查找的办法来查询最高优先权的进程,而将某个
进入就绪态的进程也很容易就根据其PID插入到就绪数组中去;
方案三、
这个方案就是采取和ucosII的方案一样,在此不再详细说明;
方案四、
用二叉树数据结构来实现,由于这种数据结构比较直白,这里也不说明;
/*****************************************************************************************************
方案选择:
由于本系统适用于低端单片机领域,所以所用的数据结构应该省RAM,所用算法应该省时间,这样,方案4、就应该是
快速,且容易扩展的方案,但是太耗RAM,方案三和ucosII的一样,有版权问题故也不应该用,由于方案一是一个取、
优先进程和插入就绪表的时间对等性不同,且由于队列是比方案二中的数据结构复杂,根据越简单越稳定的原则,选
择方案二;

_OS_PRDYTLBINDEX  _os_prdytlbindex; //进程就绪表索引数值,此处是一个无符号整型变量;
//进程就绪表索引数值,是一个具有256个元素的数组;    
const
_OS_PRDYTLB  _os_prdytlb[256]={
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
4,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
5,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
4,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
6,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
4,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
5,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
4,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
7,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
4,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
5,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
4,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
6,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
4,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
5,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
4,
0, 1, 0,
2, 0, 1,
0, 3, 0,
1, 0, 2,
0, 1, 0,
0
};

/*****************************************************************************************************
方案确定:
对于低端嵌入式,甚至高端嵌入式系统一般它的任务范围不会超过16个任务,但是为了此系统的通用性更强应该将其
设置成可设置形式,8、16、32、64、128…等等;
1、根据先易后难的原则先是实现8个进程和16六个进程可选的形式;
2、最坏切换时间确定为不超过1ms;
3、系统自带一个IDLE进程,且优先级最低,它什么也不做(几乎是现在所有的操作系统的做法)
4、系统自带几个可选的进程(待定)
/*****************************************************************************************************

#endif

 

os.h文件,未完待续