本文最后更新于:2023年9月25日 下午
1.实现延时的系统调用
首先在syscall.asm中定义系统调用
1 2 3 4 5 6 7 8 9 10
| _NR_mills_sleep equ 1 ;设置系统调用 global mills_sleep ; 导出符号 mills_sleep: mov eax, _NR_mills_sleep mov ecx, [esp+4];由于需要参数 int INT_VECTOR_SYS_CALL ret
|
由于系统调用的中断向量已经被书中代码实现,故我们只需要设置即可。
在const.h中设置系统调用个数
#define NR_SYS_CALL 2
然后去global.c中修改系统调用表
PUBLIC system_call sys_call_table[NR_SYS_CALL] = {sys_get_ticks,sys_mills_sleep};
系统调用表实际上就是函数指针,到这一步,系统已经可以接受你的系统调用并按照分配好的函数名进行调用了!下一步只要实现这个函数就好。
1 2 3 4 5 6 7 8 9 10 11
| int wake_tick;
PUBILC void sys_mills_sleep(int milli_seconds){ p_proc_ready->wake_tick = get_ticks() + milli_seconds / (1000 / HZ); schedule(); }
PUBLIC void sys_mills_sleep(int milli_seconds); PUBLIC void mills_sleep(int milli_seconds);
|
但是目前设置的“sleep”并没有真的让进程停下来,它只是为进程设置了一个“唤醒时间”。为了真的做到sleep,我们需要修改调度算法。
新建一个工具函数用于判断进程是否可用。
1 2 3 4 5 6 7
| PUBLIC int isRunnable(PROCESS* p){ if(p->wakeup_ticks <= get_ticks()&&p->isBlock == 0&&p->isDone ==0){ return 1; }else{ return 0; } }
|
在Schedule中判断进程必须可用才行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| PUBLIC void schedule() { PROCESS* p; int greatest_ticks = 0;
while (!greatest_ticks) { for (p = proc_table; p < proc_table+NR_TASKS; p++) { if (p->ticks > greatest_ticks&&isRunnable(p)) { greatest_ticks = p->ticks; p_proc_ready = p; } }
if (!greatest_ticks) { for (p = proc_table; p < proc_table+NR_TASKS; p++) { p->ticks = p->priority; } } } }
|
到此,这项功能即可正常工作。
如图,将A的睡眠时间设置为B、C的10倍,可以看到A很少出现了。
还有一些报错,等待后面能解决

2.包装实现输出的系统调用
采用类似上述步骤,配置新增一个系统调用的过程。此处仅介绍一下具体的输出函数。
考虑到是要对每一个任务用不同的颜色,同一个进程不会有不同颜色。因此,我们只需要把进程的号作为不同颜色即可
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
| PUBLIC void sys_my_print(char* str){ if (disp_pos > 80 * 25 * 2){ return; } switch(p_proc_ready - proc_table){ case 0: disp_color_str(str, BRIGHT | MAKE_COLOR(BLACK, RED)); break; case 1: disp_color_str(str, BRIGHT | MAKE_COLOR(BLACK, GREEN)); break; case 2: disp_color_str(str, BRIGHT | MAKE_COLOR(BLACK, BLUE)); break; case 5: disp_str(str); break; case 4: disp_color_str(str, BRIGHT | MAKE_COLOR(BLACK, PURPLE)); break; case 3: disp_color_str(str, BRIGHT | MAKE_COLOR(BLACK, YELLO)); break; default: disp_str(str); break; } }
|
3.PV操作
3.1 新建几个进程
参考Orange‘S 6.4.6的内容,为系统添加三个额外进程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| void WriterD() { while(1){ my_print("D."); mills_sleep(10); } } void WriterE() { while(1){ my_print("E."); mills_sleep(10); } } void NormalF() { while(1){ my_print("F."); mills_sleep(10); } }
|

3.2 PV操作系统调用
按照1中所述的添加系统调用的方法添加P、V两个系统调用。
首先在global.h中添加Semaphore的定义
1 2 3 4
| typedef struct semaphore{ int value; PROCESS* queue[NR_TASKS]; }Semaphore;
|
然后完成对PV操作的实现
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
|
PUBLIC void sys_P(void *mutex){ disable_irq(CLOCK_IRQ); Semaphore *semaphore = (Semaphore *)mutex; semaphore->value--; if (semaphore->value < 0){ block(semaphore); } enable_irq(CLOCK_IRQ); }
PUBLIC void block(Semaphore *mutex){ mutex->queue[-mutex->value - 1] = p_proc_ready; p_proc_ready->isBlock = 1; schedule(); }
PUBLIC void sys_V(void *mutex){ disable_irq(CLOCK_IRQ); Semaphore *semaphore = (Semaphore *)mutex; semaphore->value++; if (semaphore->value <= 0){ wake(semaphore); } enable_irq(CLOCK_IRQ); }
PUBLIC void wake(Semaphore *mutex){ mutex->queue[0]->isBlock = 0; for(int i=0;i<-mutex->value;i++){ mutex->queue[i] = mutex->queue[i+1]; } }
|
3.3 基于此背景下的调度算法
应该首先判断F进程是否可以运行,如果可以应该首先运行F进程,用于监视操作。然后应该按照进程顺序进行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| PUBLIC void schedule() { isAllDone(); PROCESS* p = proc_table+5; if(isRunnable(p)){ p_proc_ready = p; } else{ while(!isRunnable(ptr_schedule)){ ptr_schedule++; if(ptr_schedule==p){ ptr_schedule = proc_table; } } p_proc_ready = ptr_schedule; ptr_schedule++; if(ptr_schedule==p){ ptr_schedule = proc_table; } } if(p_proc_ready-proc_table<=4){ nowStatus = p_proc_ready-proc_table; } }
|
4. 读优先算法
read
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
| while(1){ P(&countMutex); if (readPreparedCount == 0) { P(&writeMutex); } readPreparedCount++; V(&countMutex);
P(&readMutex); readCount++; my_print(pname); my_print(" start. "); int j; for (j = 0; j < p_proc_ready->priority; ++j) { my_print(pname); my_print(readStr); if (j == p_proc_ready->priority - 1) { my_print(pname); my_print(endStr); } else { milli_delay(10); } } readCount--; V(&readMutex);
P(&countMutex); readPreparedCount--; if (readPreparedCount == 0) { V(&writeMutex); } V(&countMutex);
p_proc_ready->isDone = solveHunger; milli_delay(10); }
|
write
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
| while (1){ P(&writeMutexMutex); P(&writeMutex); my_print(pname); my_print(" start. "); int j; for (j = 0; j < p_proc_ready->priority; ++j) { my_print(pname); my_print(writeStr); if (j == p_proc_ready->priority - 1) { my_print(pname); my_print(endStr); } else { milli_delay(10); } } V(&writeMutex); V(&writeMutexMutex);
p_proc_ready->isDone = solveHunger; milli_delay(10); }
|
截图



5.写优先算法
reader
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
| while (1) { P(&readPermissionMutex); P(&readPermission); P(&readCountMutex); if (readPreparedCount == 0) { P(&writeMutex); } readPreparedCount++; V(&readCountMutex); V(&readPermission); V(&readPermissionMutex);
P(&readMutex); readCount++; my_print(pname); my_print(" start. "); int j; for (j = 0; j < p_proc_ready->priority; ++j) { my_print(pname); my_print(readStr); if (j == p_proc_ready->priority- 1) { my_print(pname); my_print(endStr); } else { milli_delay(10); } } readCount--; V(&readMutex);
P(&readCountMutex); readPreparedCount--; if (readPreparedCount == 0) { V(&writeMutex); } V(&readCountMutex);
p_proc_ready->isDone = solveHunger; milli_delay(10); }
|
writer
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
| while (1) { P(&writeCountMutex); if(writeCount==0){ P(&readPermission); } writeCount++; V(&writeCountMutex); P(&writeMutex); my_print(pname); my_print(" start. "); int j; for (j = 0; j < p_proc_ready->priority; ++j) { my_print(pname); my_print(writeStr); if (j == p_proc_ready->priority - 1) { my_print(pname); my_print(endStr); } else { milli_delay(10); } } V(&writeMutex);
P(&writeCountMutex); writeCount--; if (writeCount == 0) { V(&readPermission); } V(&writeCountMutex);
p_proc_ready->isDone = solveHunger; milli_delay(10); }
|
截图


