shell的本质

taskA wait (“TaskB”)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef struct
{
RegValue rv; //寄存器的值,记录任务执行状态
Descriptor ldt[3]; //局部段描述符表,LDT描述局部于每个程序的段,包括代码段、数据段、显存段
ushort ldtSelector; //LDT选择子
ushort tssSelector; //TSS,用于查询内核栈
void (*tmain)(); //任务起始地址
uint id; //任务id
ushort current; //任务已经执行的时间
ushort total; //执行队列中 任务总共允许执行的时间
char name[16]; //任务名
Queue wait; //被此任务的等待队列
byte* stack; //任务栈
Event* event; //任务事件
} Task;

taskA移入taskB的等待队列

image-20220904191139046

taskB结束后要将taskB的等待队列的任务取出来

image-20220904191559676

功能函数

查找任务FindTaskByName

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static Task* FindTaskByName(const char* name)
{
Task* ret = NULL;
//IdleTask任务直接返回空
if( !StrCmp(name, "IdleTask", -1) )
{
int i = 0;
//遍历gTaskBuff数组
for(i=0; i<MAX_TASK_BUFF_NUM; i++)
{
TaskNode* tn = AddrOff(gTaskBuff, i);
//id不为0且比较字符串相等
if( tn->task.id && StrCmp(tn->task.name, name, -1) )
{
ret = &tn->task;
break;
}
}
}
//返回目标任务地址
return ret;
}

waitTask

根据名字找到目标任务后,将当前任务放入目标任务的等待队列中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void WaitTask(const char* name)
{
Task* task = FindTaskByName(name);

if( task )
{
Event* evt = CreateEvent(TaskEvent, (uint)task, 0, 0);

if( evt )
{ //不同事件不同处理函数
EventSchedule(WAIT, evt);
}
}
}

事件

事件产生:任务进入等待状态

事件销毁:任务进入可执行状态

当任务请求输入时(调用readkey()时)产生事件,任务进入等待

task模块根据事件描述执行具体的调度动作(调度进哪一个等待队列)

事件定义:触发事件在就绪状态和等待状态之间的切换的因素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
enum
{
NoneEvent,
MutexEvent,
KeyEvent,
TaskEvent
};

typedef struct
{
uint type; //事件类型
uint id; //事件标识信息
uint param1; //事件参数1
uint param2; //事件参数2
} Event;

Event* CreateEvent(uint type, uint id, uint param1, uint param2)
{
Event* ret = Malloc(sizeof(Event));

if( ret )
{
ret->type = type;
ret->id = id;
ret->param1 = param1;
ret->param2 = param2;
}

return ret;
}

void DestroyEvent(Event* event)
{
Free(event);
}

事件机制的设计

由于当前任务出现了事件,因此需要记录当前事件的信息并且将当前任务进入某个等待队列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//根据事件把任务从等待状态调度为就绪状态还是从就绪状态调度为等待状态
// typedef struct
// {
// uint type;
// uint id;
// uint param1;
// uint param2;
// } Event;
void EventSchedule(uint action, Event* event)
{
switch(event->type)
{
case KeyEvent:
KeySchedule(action, event);
break;
case TaskEvent:
TaskSchedule(action, event);
break;
case MutexEvent:
MutexSchedule(action, event);
break;
default:
break;
}
}

static void TaskSchedule(uint action, Event* event)
{
Task* task = (Task*)event->id;

if( action == NOTIFY )
{
WaittingToReady(&task->wait);
}
else if( action == WAIT )
{
//gCTask 进入 目标任务的等待队列
WaitEvent(&task->wait, event);
}
}

static void MutexSchedule(uint action, Event* event)
{
Mutex* mutex = (Mutex*)event->id;

if( action == NOTIFY )
{
WaittingToReady(&mutex->wait);
}
else if( action == WAIT )
{
////gCTask 进入 目标互斥锁的等待队列
WaitEvent(&mutex->wait, event);
}
}

static void WaitEvent(Queue* wait, Event* event)
{
//当前任务记录事件
gCTaskAddr->event = event;
//当前任务放入目标等待队列
RunningToWaitting(wait);
//调度下一个任务执行
ScheduleNext();
}

task模块

根据事件执行调度,根据不同的事件进入不同等待队列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void WaitTask(const char* name)
{
Task* task = FindTaskByName(name);

if( task )
{
Event* evt = CreateEvent(TaskEvent, (uint)task, 0, 0);

if( evt )
{
//当前任务进入 目标任务的等待队列
EventSchedule(WAIT, evt);//taslSchedule
}
}
}

mutex模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
static void DoWait(Mutex* mutex, uint* wait)
{
Event* evt = CreateEvent(MutexEvent, (uint)mutex, 0, 0);

if( evt )
{
*wait = 1;
//当前任务 进入 目标互斥锁的等待队列
EventSchedule(WAIT, evt);//MutexSchedule
}
}

static void SysNormalEnter(Mutex* mutex, uint* wait)
{
if( mutex->lock )//锁是否已经被获取
{
DoWait(mutex, wait);
}
else //
{
mutex->lock = 1;
*wait = 0;
}
}