《操作系统》实验报告二

Shell及系统调用

一、  实验内容

    1. 巩固操作系统的进程调度机制和策略
    1. 熟悉MINIX系统调用和MINIX调度器的实现

二、实验要求

  • 在MINIX3中实现Earliest-Deadline-First近似实时调度功能:
    1. 提供设置进程执行期限的系统调度chrt (long deadline),用于将调用该系统调用的进程设为实时进程,其执行的期限为:从调用处开始deadline秒。
    1. 在内核进程表中需要增加一个条目,用于表示进程的实时属性;修改相关代码,新增一个系统调用chrt,用于设置其进程表中的实时属性。
    1. 修改proc.c和proc.h中相关的调度代码,实现最早deadline的用户进程相对于其它用户进程具有更高的优先级,从而被优先调度运行。
    1. 在用户程序中,可以在不同位置调用多次chrt系统调用,在未到deadline之前,调用chrt将会改变该程序的deadline。
    1. 未调用chrt的程序将以普通的用户进程(非实时进程)在系统中运行。

三、注意事项

  1. MINIX的不同服务模块和内核都是运行在不同进程中,只能使用基于消息的进程间系统调用/内核调用,不能使用直接调用普通C函数。
  2. 添加调用编号,需要修改取值范围限制。
  3. 以源码为准(博客等资料版本落后)。
  4. 善用source insight高级功能(调用关系,全局搜索)。
  5. 善用git diff 检查代码修改。修改涉及文件较多,git diff可直观看到修改内容,避免引入无意的错误。
  6. 善用FileZilla功能。连接虚拟机,拉取需修改的文件,修改后上传到虚拟机。
  7. 消息结构体在include/minix/ipc.h中

四、实验准备

  1. 下载源码
cd /usr
git clone git://git.minix3.org/minix src
git branch –a # 查看代码版本
git checkout R3.3.0 # 将代码版本切换为 3.3.0

得到虚拟机上有如下文件

  1. 编译
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);
}

得到结果如图所示

六、参考资料

  1. 如何添加Minix内核调用
    https://wiki.minix3.org/doku.php?id=developersguide:newkernelcall
  2. Minix内核调用APIs
    http://wiki.minix3.org/doku.php?id=developersguide:kernelapi
  3. 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近似实时调度功能相关推荐

  1. linux什么是实时调度,Linux中的实时调度

    svenfx.. 17 在实时调度中,FIFO和RR与非实时调度具有完全相同的含义.始终以FIFO方式选择过程,然而,与SCHED_RR的时间量不同,SCHED_FIFO的时间量不受限制. SCHED ...

  2. linux 进程状态显示dl,Linux系统中的实时调度器DL调度器的原理是什么?详细概述...

    一.概述 实时系统是这样的一种计算系统:当事件发生后,它必须在确定的时间范围内做出响应.在实时系统中,产生正确的结果不仅依赖于系统正确的逻辑动作,而且依赖于逻辑动作的时序.换句话说,当系统收到某个请求 ...

  3. 域控制器安装过程中断电!与Windows Server 2008 林功能级别提升之“冬夜”分享...

    域控制器安装过程中断电!与Windows Server 2008 林功能级别提升之"冬夜"分享 记得上一次删除脱线域控制器的时间还是在11个月前,在一台老掉牙的机器上操作着那个几乎 ...

  4. 【Linux 内核】实时调度类 ⑦ ( 实时调度类核心函数源码分析 | dequeue_task_rt 函数 | 从执行队列中移除进程 )

    文章目录 一.dequeue_task_rt 函数 ( 从执行队列中移除进程 ) 二.update_curr_rt 函数 ( 更新调度信息 ) 本篇博客中 , 开始分析 struct sched_cl ...

  5. 【Linux 内核】实时调度类 ⑥ ( 实时调度类核心函数源码分析 | 插入进程到执行队列 | 从执行队列中选择优先级最高的进程 )

    文章目录 一.enqueue_task_rt 函数 ( 插入进程到执行队列 ) 二.pick_next_task_rt 函数 ( 从执行队列中选择优先级最高的进程 ) 本篇博客中 , 开始分析 str ...

  6. 文本编辑器中实现设置工具栏和状态栏可见性的功能

    文章目录 1 文本编辑器中实现设置工具栏和状态栏可见性的功能 1 文本编辑器中实现设置工具栏和状态栏可见性的功能 实现思路如下: 通过setVisible()设置可见性. 更新界面上QAction对象 ...

  7. android中注册的账号密码储存在,Android中使用SharedPreferences完成记住账号密码的功能...

    效果图: 记住密码后,再次登录就会出现账号密码,否则没有. 分析: SharedPreferences可将数据存储到本地的配置文件中 SharedPreferences会记录CheckBox的状态,如 ...

  8. DevExpress 中 在做全选的全消功能的时候 加快效率

    DevExpress 中 在做全选的全消功能的时候 加快效率 在做 DevExpress 中对增加的选择 Check列 控制全选的全消时通过以下代码红色字代码效率会有明显的提升: private vo ...

  9. C语言试题五十五之m个人的成绩存放在score数组中,请编写函数function,它的功能是:将高于平均分的人数作为函数值返回,将高于平均分的分数放在high所指定的数组中。

    1. 题目 m个人的成绩存放在score数组中,请编写函数function,它的功能是:将高于平均分的人数作为函数值返回,将高于平均分的分数放在high所指定的数组中. 2 .温馨提示 C语言试题汇总 ...

  10. C语言试题十二之m个人的成绩存放在score数组中,请编写函数function,它的功能是:将低于平均分的人数作为函数值返回,将低于平均分的分数放在below所指定的数组中。

    1. 题目 m个人的成绩存放在score数组中,请编写函数function,它的功能是:将低于平均分的人作为函数值返回,将低于平均分的分数放在below所指定的数组中. 2 .温馨提示 C语言试题汇总 ...

最新文章

  1. oracle 开链,欧链OracleChain开启Dapps应用新时代
  2. 一文全览机器学习建模流程(Python代码)
  3. 硬件信息统计_读取输出Excel_显示进度
  4. python des加密文件_Python DES加密解密方法 pyDes库 兼容中文
  5. 视觉slam第一讲——
  6. Python CGI编程
  7. AMD 和 CMD 的区别有哪些?
  8. 计算机毕业设计-基于SSM的酒店客房管理系统-JavaWeb酒店客房管理系统
  9. iOS在服务器返回的JSON字符串带火星文乱码的处理
  10. DeepLearning初窥门径
  11. 微博自动同步发表到微头条工具使用说明
  12. 交换机与路由器的基本工作原理
  13. 24点计算器c语言源代码,萌新求助!!24点游戏计算器
  14. Java定时任务的实现
  15. MYSQL正则匹配手机号码
  16. jadx 支持 Windows、Linux、 macOS,能够帮我们打开.apk, .dex, .jar,.zip等格式的文件
  17. 城市NOA赛道,这家“本土巨头”如何实现系统性能颠覆升级?
  18. Mac上虚拟机软件哪个好?Mac上最好用的虚拟机软件是哪个?
  19. android 5.1 正在运行,android5.1在x86上运行稳定吗
  20. 易飞 如何制作自定义报表

热门文章

  1. VC中.pch是什么文件,没有.pch文件怎么办
  2. SQL 注入速查表大全
  3. wps如何自己制作流程图_怎么制作流程图,wps自动生成流程图方法
  4. 寄存器 SRAM DRAM存储单元区别
  5. ubuntu下安装goldendict及离线词库
  6. python识别图片背景中数字_用python识别一张数字图片
  7. 微信平台分账产品怎么选?
  8. python中base函数_详细的python basemap中各函数的所有参量注释
  9. word2016 页码问题
  10. h标签,b标签,em,i ,u,s标签