在MINIX3中实现Earliest-Deadline-First近似实时调度功能
《操作系统》实验报告二
Shell及系统调用
一、 实验内容
- 巩固操作系统的进程调度机制和策略
- 熟悉MINIX系统调用和MINIX调度器的实现
二、实验要求
- 在MINIX3中实现Earliest-Deadline-First近似实时调度功能:
- 提供设置进程执行期限的系统调度chrt (long deadline),用于将调用该系统调用的进程设为实时进程,其执行的期限为:从调用处开始deadline秒。
- 在内核进程表中需要增加一个条目,用于表示进程的实时属性;修改相关代码,新增一个系统调用chrt,用于设置其进程表中的实时属性。
- 修改proc.c和proc.h中相关的调度代码,实现最早deadline的用户进程相对于其它用户进程具有更高的优先级,从而被优先调度运行。
- 在用户程序中,可以在不同位置调用多次chrt系统调用,在未到deadline之前,调用chrt将会改变该程序的deadline。
- 未调用chrt的程序将以普通的用户进程(非实时进程)在系统中运行。
三、注意事项
- MINIX的不同服务模块和内核都是运行在不同进程中,只能使用基于消息的进程间系统调用/内核调用,不能使用直接调用普通C函数。
- 添加调用编号,需要修改取值范围限制。
- 以源码为准(博客等资料版本落后)。
- 善用source insight高级功能(调用关系,全局搜索)。
- 善用git diff 检查代码修改。修改涉及文件较多,git diff可直观看到修改内容,避免引入无意的错误。
- 善用FileZilla功能。连接虚拟机,拉取需修改的文件,修改后上传到虚拟机。
- 消息结构体在include/minix/ipc.h中
四、实验准备
- 下载源码
cd /usr
git clone git://git.minix3.org/minix src
git branch –a # 查看代码版本
git checkout R3.3.0 # 将代码版本切换为 3.3.0
得到虚拟机上有如下文件
- 编译
cd /usr/src
make build #首次编译以及修改了头文件
make build MKUPDATE #增量式编译
首次编译用时较长
3. 内核串口调试
- 在vmware虚拟机关闭情况下,在设置中点击添加设备,再选择添加串口,简单情况下可以使用物理机文件output.txt作为串口输出目标。
- 启动虚拟机,运行 echo “hello world” > /dev/tty00,可以在output.txt中观察到hello world的输出结果。
- 在内核调试中,可以通过向/dev/tty00文件写入字符的形式进行调试
五、实验过程
- 增加系统调用chrt:
1. 应用层:需要添加的系统调用chrt可以定义在unistd头文件中,并在libc中添加chrt函数体实现- 在/usr/src/include/unistd.h 中添加chrt函数定义
// 加入到适当的位置
int chrt(long); //定义chrt函数
- 在/usr/src/minix/lib/libc/sys/chrt.c中添加chrt函数实现。可用alarm函数实现超时强制终止
chrt的功能主要是要将参数deadline添加到message信息中,然后利用_syscall()函数通信息结构体进行IPC通信,传递deadline
具体代码实现参考同文件夹下的fork.c中实现fork函数的代码
#include <sys/cdefs.h>
#include "namespace.h"
#include <lib.h>
#include <string.h>
#include <unistd.h>
#ifdef __weak_alias
__weak_alias(fork, _fork)
#endif
pid_t fork(void)
{message m;memset(&m, 0, sizeof(m));return(_syscall(PM_PROC_NR, PM_FORK, &m));
}
注意的一点是可以在usr/src/minix/include/minix/ipc.h文件中查找到message结构体中long型数据的存储形式如下
typedef struct {int64_t m2ll1;int m2i1, m2i2, m2i3;long m2l1, m2l2;char *m2p1;sigset_t sigset;short m2s1;uint8_t padding[6];
} mess_2;
_ASSERT_MSG_SIZE(mess_2);typeofdef struct{/*......*/union{/*......*/mess_2 m_m2/*......*/}/*......*/
} message __aligned(16);#define m2_l2 m_m2.m2l2
可以得到long型数据存储位置
因为message中应包含进程结束时的时间,所以还需要获取到现在系统的时间加上设置的deadline来得message中应该传输的时间
系统时间通过time.tv_sec得到
所以整合上述要点后可以写出chrt.c代码
/* chrt.c */
#include <sys/cdefs.h>
#include "namespace.h"
#include <lib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>int chrt(long deadline){struct timespec time;message m;memset(&m, 0, sizeof(m));alarm((unsigned int)deadline);if (deadline < 0){return 0;}if (deadline > 0){clock_gettime(CLOCK_REALTIME,&time);deadline = time.tv_sec + deadline; //向服务层发送的信息为实际应该结束的时间}m.m2_l1 = deadline;return (_syscall(PM_PROC_NR, PM_CHRT, &m));
}
- 在/usr/src/minix/lib/libc/sys中Makefile.inc文件添加chrt.c条目
2. 服务层:需要向MINIX系统的进程管理服务中注册chrt,使得chrt服务可以向应用层提供
- 在/usr/src/minix/servers/pm/proto.h中添加chrt函数定义
这里虽然说是chrt函数的定义,但是这里定义的其实是服务层对chrt函数的处理,向内核层发送message,而不是应用层中用户使用的chrt函数。
/* chrt.c */
int do_chrt(void);
- 在/usr/src/minix/servers/pm/chrt.c中添加chrt函数实现,调用sys_chrt()
int do_chrt(){sys_chrt(who_p, m_in.m2_l1);/*sys_chrt()的参数来自同文件下的glo.h*/return (OK);
}
- 同样地在同文件夹下的Makefile文件中添加chrt条目
SRCS= main.c forkexit.c exec.c time.c alarm.c \signal.c utility.c table.c trace.c getset.c misc.c \profile.c mcontext.c schedule.c chrt.c
- 在/usr/src/minix/include/minix/callnr.h中定义PM_CHRT编号
#define PM_CHRT (PM_BASE + 48)#define NR_PM_CALLS 49 /* highest number from base plus one */
- 在/usr/src/minix/servers/pm/table.c 中调用映射表
CALL(PM_CHRT) = do_chrt
- 在/usr/src/minix/include/minix/syslib.h 中添加 sys_ chrt () 定义
/* sys_chrt() */
int sys_chrt(endpoint_t proc_ep, long deadline);
- 在/usr/src/minix/lib/libsys/sys_chrt.c 中添加 sys_chrt () 实现
#include "syslib.h"int sys_chrt(proc_ep,deadline)
endpoint_t proc_ep; /* which proc_ep has exited */
long deadline;
{/* A proc_ep has to be signaled via PM. Tell the kernel. */message m;m.m2_i1 = proc_ep;m.m2_l1 = deadline;return(_kernel_call(SYS_CHRT, &m));
}
- 在/usr/src/minix/lib/libsys 中的 Makefile 中添加 sys_chrt.c 条目
3. 内核层:在MINIX内核中实现进程调度功能,此处可以直接修改内核信息,例如进程的截至时间 - 在/usr/src/minix/kernel/system.h中添加do_chrt函数定义
- 在/usr/src/minix/kernel/config.h中将USE_CHRT设为1
#define USE_CHRT
- 在/usr/src/minix/kernel/system/do_chrt.c中添加do_chrt函数实现
#include "kernel/system.h"
#include <minix/endpoint.h>
#include "kernel/vm.h"
#include <signal.h>
#include <string.h>
#include <assert.h>
#include <minix/u64.h>/*===========================================================================** do_chrt **===========================================================================*/#if USE_CHRT
int do_chrt(struct proc *caller, message *m_ptr){struct proc *rp;rp = proc_addr(m_ptr->m2_i1);rp->p_deadline = m_ptr->m2_l1;return (OK);
}
#endif /* USE_CHRT */
- 在/usr/src/minix/kernel/system/ 中Makefile.inc文件添加do_chrt.c条目
- 在/usr/src/minix/include/minix/com.h中定义SYS_CHRT编号
# define SYS_CHRT (KERNEL_CALL + 58)/* Total */
#define NR_SYS_CALLS 59 /* number of kernel calls */
- 在/usr/src/minix/kernel/system.c 中添加SYS_CHRT编号到do_chrt的映射
map(SYS_CHRT, do_chrt);
- 在/usr/src/minix/commands/service/parse.c的system_tab中添加名称编号
{ "CHRT", SYS_CHRT },
4. 进程调度:修改影响进程调度顺序的部分
- 在/usr/src/minix/kernel/proc.h struct proc 维护每个进程的信息,用于调度决策。添加deadline成员
struct proc {long p_deadline; /*进程deadline项*/......
}
- 在/usr/src/minix/kernel/proc.c修改enqueue_head(),enqueue(),pick_proc()
- enqueue_head() 按优先级将进程加入列队首。实验中需要将实时进程的优先级设置成合适的优先级
if (rp->p_deadline>=0){rp->p_priority = 5;}
- enqueue() 按优先级将进程加入列队尾
- pick_proc() 从队列中返回一个可调度的进程 。遍历设置的优先级队列,返回剩余时间最小并可运行的进程
static struct proc * pick_proc(void)
{/* Decide who to run now. A new process is selected an returned.* When a billable process is selected, record it in 'bill_ptr', so that the * clock task can tell who to bill for system time.** This function always uses the run queues of the local cpu!*/register struct proc *rp,*tmp; /* process to run */struct proc **rdy_head;int q; /* iterate over queues *//* Check each of the scheduling queues for ready processes. The number of* queues is defined in proc.h, and priorities are set in the task table.* If there are no processes ready to run, return NULL.*/rdy_head = get_cpulocal_var(run_q_head);for (q=0; q < NR_SCHED_QUEUES; q++) { if(!(rp = rdy_head[q])) {TRACE(VF_PICKPROC, printf("cpu %d queue %d empty\n", cpuid, q););continue;}assert(proc_is_runnable(rp));if(q==5){rp = rdy_head[q];tmp = rp->p_nextready;while (tmp!=NULL){if(tmp->p_deadline > 0){if(tmp->p_deadline < rp->p_deadline){if (proc_is_runnable(tmp)){rp = tmp;}}}tmp = tmp->p_nextready;}if (priv(rp)->s_flags & BILLABLE) get_cpulocal_var(bill_ptr) = rp; /* bill for system time */return rp;}}return NULL;
}
五、测试运行
将下面代码上传到重新编译后的虚拟机中,编译运行
/* test-2.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <lib.h>
#include <time.h>void proc(int id);
int main(void)
{//创建三个子进程,并赋予子进程idfor (int i = 1; i < 4; i++){if (fork() == 0){proc(i);}}return 0;
}
void proc(int id)
{int loop;switch (id){case 1: //子进程1,设置deadline=25chrt(25);printf("proc1 set success\n");sleep(1);break;case 2: //子进程2,设置deadline=15chrt(15);printf("proc2 set success\n");sleep(1);break;case 3: //子进程3,普通进程chrt(0);printf("proc3 set success\n");break;}for (loop = 1; loop < 40; loop++){//子进程1在5s后设置deadline=5if (id == 1 && loop == 5){chrt(5);printf("Change proc1 deadline to 5s\n");}//子进程3在10s后设置deadline=3if (id == 3 && loop == 10){chrt(3);printf("Change proc3 deadline to 3s\n");}sleep(1); //睡眠,否则会打印很多信息printf("prc%d heart beat %d\n", id, loop);}exit(0);
}
得到结果如图所示
六、参考资料
- 如何添加Minix内核调用
https://wiki.minix3.org/doku.php?id=developersguide:newkernelcall - Minix内核调用APIs
http://wiki.minix3.org/doku.php?id=developersguide:kernelapi - Minix讨论区
https://groups.google.com/forum/#!forum/minix3
七、备注
因为Minix源码在虚拟机上下载太满了,所以我在网上找到了一个gitee上的源码,如有需要可以去我的仓库中获取或者去源仓库获取。
我的仓库:https://gitee.com/zhongershun/minix
源仓库:https://gitee.com/jiangsheng1987/minix
另外,本次实验报告本人也已将将完整的修改后代码以及实验报告上传至GitHub仓库
GitHub:https://github.com/zhongershun/os-Earliest-Deadline-First
如有问题,欢迎指正。
在MINIX3中实现Earliest-Deadline-First近似实时调度功能相关推荐
- linux什么是实时调度,Linux中的实时调度
svenfx.. 17 在实时调度中,FIFO和RR与非实时调度具有完全相同的含义.始终以FIFO方式选择过程,然而,与SCHED_RR的时间量不同,SCHED_FIFO的时间量不受限制. SCHED ...
- linux 进程状态显示dl,Linux系统中的实时调度器DL调度器的原理是什么?详细概述...
一.概述 实时系统是这样的一种计算系统:当事件发生后,它必须在确定的时间范围内做出响应.在实时系统中,产生正确的结果不仅依赖于系统正确的逻辑动作,而且依赖于逻辑动作的时序.换句话说,当系统收到某个请求 ...
- 域控制器安装过程中断电!与Windows Server 2008 林功能级别提升之“冬夜”分享...
域控制器安装过程中断电!与Windows Server 2008 林功能级别提升之"冬夜"分享 记得上一次删除脱线域控制器的时间还是在11个月前,在一台老掉牙的机器上操作着那个几乎 ...
- 【Linux 内核】实时调度类 ⑦ ( 实时调度类核心函数源码分析 | dequeue_task_rt 函数 | 从执行队列中移除进程 )
文章目录 一.dequeue_task_rt 函数 ( 从执行队列中移除进程 ) 二.update_curr_rt 函数 ( 更新调度信息 ) 本篇博客中 , 开始分析 struct sched_cl ...
- 【Linux 内核】实时调度类 ⑥ ( 实时调度类核心函数源码分析 | 插入进程到执行队列 | 从执行队列中选择优先级最高的进程 )
文章目录 一.enqueue_task_rt 函数 ( 插入进程到执行队列 ) 二.pick_next_task_rt 函数 ( 从执行队列中选择优先级最高的进程 ) 本篇博客中 , 开始分析 str ...
- 文本编辑器中实现设置工具栏和状态栏可见性的功能
文章目录 1 文本编辑器中实现设置工具栏和状态栏可见性的功能 1 文本编辑器中实现设置工具栏和状态栏可见性的功能 实现思路如下: 通过setVisible()设置可见性. 更新界面上QAction对象 ...
- android中注册的账号密码储存在,Android中使用SharedPreferences完成记住账号密码的功能...
效果图: 记住密码后,再次登录就会出现账号密码,否则没有. 分析: SharedPreferences可将数据存储到本地的配置文件中 SharedPreferences会记录CheckBox的状态,如 ...
- DevExpress 中 在做全选的全消功能的时候 加快效率
DevExpress 中 在做全选的全消功能的时候 加快效率 在做 DevExpress 中对增加的选择 Check列 控制全选的全消时通过以下代码红色字代码效率会有明显的提升: private vo ...
- C语言试题五十五之m个人的成绩存放在score数组中,请编写函数function,它的功能是:将高于平均分的人数作为函数值返回,将高于平均分的分数放在high所指定的数组中。
1. 题目 m个人的成绩存放在score数组中,请编写函数function,它的功能是:将高于平均分的人数作为函数值返回,将高于平均分的分数放在high所指定的数组中. 2 .温馨提示 C语言试题汇总 ...
- C语言试题十二之m个人的成绩存放在score数组中,请编写函数function,它的功能是:将低于平均分的人数作为函数值返回,将低于平均分的分数放在below所指定的数组中。
1. 题目 m个人的成绩存放在score数组中,请编写函数function,它的功能是:将低于平均分的人作为函数值返回,将低于平均分的分数放在below所指定的数组中. 2 .温馨提示 C语言试题汇总 ...
最新文章
- oracle 开链,欧链OracleChain开启Dapps应用新时代
- 一文全览机器学习建模流程(Python代码)
- 硬件信息统计_读取输出Excel_显示进度
- python des加密文件_Python DES加密解密方法 pyDes库 兼容中文
- 视觉slam第一讲——
- Python CGI编程
- AMD 和 CMD 的区别有哪些?
- 计算机毕业设计-基于SSM的酒店客房管理系统-JavaWeb酒店客房管理系统
- iOS在服务器返回的JSON字符串带火星文乱码的处理
- DeepLearning初窥门径
- 微博自动同步发表到微头条工具使用说明
- 交换机与路由器的基本工作原理
- 24点计算器c语言源代码,萌新求助!!24点游戏计算器
- Java定时任务的实现
- MYSQL正则匹配手机号码
- jadx 支持 Windows、Linux、 macOS,能够帮我们打开.apk, .dex, .jar,.zip等格式的文件
- 城市NOA赛道,这家“本土巨头”如何实现系统性能颠覆升级?
- Mac上虚拟机软件哪个好?Mac上最好用的虚拟机软件是哪个?
- android 5.1 正在运行,android5.1在x86上运行稳定吗
- 易飞 如何制作自定义报表