【LittleXi】【MIT6.S081-2022Fall】Lab: syscall

news2024/11/20 7:03:51

【LittleXi】【MIT6.S081-2022Fall】Lab: syscall

文章目录

  • lab2
    • 实验1:Process counting
      • 实验思路
      • 实验过程
    • 实验2:Free Memory Cou
      • 实验思路
      • 实验过程
    • 实验3:System call tracin
      • 实验思路
      • 实验过程
    • 实验4:流程概述
      • 1.请概述用户从发出系统调用指令到得到返回结果的执行的流程。
      • 2.搜索资料,概述malloc的底层实现原理
    • 实验过程中遇到的问题及解决方案
      • 遇到的问题:
      • 解决方案:
    • 实验总结

lab2

实验1:Process counting

实验思路

1、实验要求我们增加一个新的系统调用procnum,统计系统总进程数。

2、那么我们只需要按照实验准备的工作的五个步骤去添加(最开始并没有注意到每个地方添加的意义是什么,所以直接原封不动添加了SYS_new_syscal,然后感觉不太对劲)

3、添加实验准备后,然后就可以直接开始计数了,计数步骤很简单,(最开始误以为进程挂载在CPU上,导致出错)直接遍历proc数组就行了,注意数组的长度为NPROC ,然后简单计数一下就行了

实验过程

1、在proc.c中添加计数代码,用num计数,然后将函数声明放进defs.h文件中,保证其它文件能够调用到该函数

uint64 proccnt()
{
  uint64 num = 0;
  for(int i=0;i<NPROC;i++)
  {
    acquire(&proc[i].lock);
    num+=proc[i].state != UNUSED;
    release(&proc[i].lock);
  }
  return num;
}

2、在sysproc.c文件中添加一个系统级可调用的函数,直接返回proccnt的值

uint64 sys_procnum (void)
{
  return proccnt();
}

3、修改procnum.c文件中的num的值的获取方式,使得num的值为procnum()的返回的值

int num = -1;
if ((num = procnum()) < 0)
{
    fprintf(2, "procnum failed!\n");
    exit(1);
}
printf("Number of process: %d\n", num);
exit(0);

4、系统调用流程,先进入procnum.c文件中,然后遇到procnum函数,从user.h中去查找这个函数,接着进入syscall中去查找sys_procnum函数,进入sysproc.c中调用对应函数,然后继续调用proc.c 中的函数

5、实验运行结果

请添加图片描述

实验2:Free Memory Cou

实验思路

1、实验2和实验1高度相似,除了计数不一样之外,其它地方和实验一几乎一样

2、单独说一下计数,这个实验的计数是在kalloc.c文件中完成的,因为空闲页的管理是用指针的方式实现的 ,所以计数的方法可以先用一个指针指向空闲内存链表的表头,然后对指针进行移动,同时记录一下有多少个页被访问过了,当移到到链表的表尾的时候就停止移动,返回num*pageSize就是空闲的内存

实验过程

1、实验准备和实验一类似,不再赘述

2、计数的代码实现和实验思路第二点一样,就是利用指针的移动来进行计数

uint64 freecnt()
{
  uint64 num = 0;
  struct run* ptr = kmem.freelist;
  struct spinlock* lock = &kmem.lock;
  acquire(lock);
  while(ptr) {
    num++;
    ptr = ptr->next;
  }
  release(lock);
  return num*PGSIZE;
}

3、系统调用流程,和实验一几乎一样,不同的区别在于实验一计数是进入proc.c中,而这里是进入kalloc.c 文件

4、实验结果截图:

请添加图片描述

实验3:System call tracin

实验思路

1、本实验的前期准备和实验一和实验二一样,一共要修改makefile、user.h、usys.pl等8个文件

2、本实验的整体思路就是将读取参数中的mask保存在proc进程中,然后在进行系统级调用的时候根据掩码进行打印程序运行的pid、系统调用名称和返回值就行。

实验过程

1、修改makefile、user.h、usys.pl等8个文件和实验1、2类似,不再赘述

2、修改proc.h文件中的结构体proc,在该结构体中添加一个mask变量以保存mask参数

struct proc
{
  struct spinlock lock;
  //此处省略若干代码....
  char name[16];               // Process name (debugging)
  int mask;                    // Add mask val
};	

3、对于具有fork代码的实现,我们需要修改一下proc.c文件中的fork()函数,在子进程中我们需要copy一下父进程的mask和state

 int fork(void)
{
  int i, pid; 
  //此处省略若干代码....
  //copy mask
  np->mask = p -> mask;
  pid = np->pid;
  np->state = p->state;
  //此处省略若干代码....
  return pid;
}

4、在sysproc.c文件中实现trace函数,在函数的实现过程中可以调用argint方法,获取系统调用的参数,然后将参数保存在之前加入到的结构体proc中

uint64 sys_trace(int n)
{
  argint(0, &n);
  if ( n < 0) 
    return -1;
  myproc()->mask = n;   
  return 0;
} 

5、在syscall.c文件中,添加系统调用的识别名,并在syscall函数中添加需要输出的信息,如果当前进程的掩码和系统调用的函数是一样的,那么就输出该系统调用的pid、系统调用名称和返回值,代码实现如下

char* syscalls_name[23] = {
    "", 
    "fork",
    "exit",
    "wait",
    "pipe",
    "read",
    "kill",
    "exec",
    "fstat",
    "chdir",
    "dup",
    "getpid",
    "sbrk",
    "sleep",
    "uptime",
    "open",
    "write",
    "mknod",
    "unlink",
    "link",
    "mkdir",
    "close",
    "trace",
};
void syscall(void)
{
  int num;
  struct proc *p = myproc();
    
  num = p->trapframe->a7;
  if (num > 0 && num < NELEM(syscalls) && syscalls[num])
  {
    p->trapframe->a0 = syscalls[num]();
    if(p->mask&(1<<num))
      printf("%d: syscall %s -> %d\n",p->pid,syscalls_name[num],p->trapframe->a0);
  }
  else
  {
    printf("%d %s: unknown sys call %d\n",
           p->pid, p->name, num);
    p->trapframe->a0 = -1;
  }
}

6、实验结果截图

请添加图片描述
请添加图片描述

在这里插入图片描述

实验4:流程概述

1.请概述用户从发出系统调用指令到得到返回结果的执行的流程。

答:

  1. 用户程序发出系统调用指令: 用户程序需要与操作系统内核进行交互以执行特权操作。用户程序通过调用包装好的系统调用函数(例如procnum()freemem()trace()等)来发出系统调用请求。
  2. 陷入内核态: 当用户程序发出系统调用请求时,处理器从用户态切换到内核态。通常是通过硬件中断或异常来实现的,将程序控制权传递给内核。
  3. 系统调用处理:一旦操作系统内核获得控制权,它会根据系统调用号和参数来确定要执行的操作。内核会检查参数的有效性,然后执行请求的操作。
  4. 执行系统调用: 内核执行系统调用的实际操作,例如进程计数、空闲内存计数、跟踪调用trace等。
  5. 返回结果给用户程序: 一旦系统调用完成,内核将结果返回给用户程序,例如procnum.c文件中的procnum()函数。如果系统调用成功,返回值将是非负整数,表示操作成功的结果。如果发生错误,返回值将是一个负整数,表示错误码。
  6. 恢复用户态: 用户程序再次获得控制权,并继续执行。它可以检查系统调用的返回值以确定操作是否成功,并采取适当的措施来处理结果或错误。

总之,用户从发出系统调用指令到获得返回结果的执行流程涉及从用户态到内核态的切换、系统调用处理和结果返回。这个过程允许用户程序执行需要操作系统内核权限的任务,并获得对系统资源的访问和控制。

2.搜索资料,概述malloc的底层实现原理

答:malloc 是C语言标准库中用于动态分配内存的函数,它的底层实现原理通常涉及内存管理和操作系统的系统调用。下面是 malloc 的基本底层实现原理:

  1. 内存池管理: malloc 会维护一个内存池(memory pool),通常是一块连续的虚拟内存空间。这个内存池被分割成小块,每块用于存储用户请求的内存。内存块可以分为不同的大小类别,以便满足不同大小的内存需求。
  2. 分配内存: 当用户调用 malloc 函数请求内存时,底层实现会搜索内存池,查找一个足够大的、未被分配的内存块。这个内存块会被标记为已分配,并返回给用户程序。
  3. 内部碎片: 内存分配可能会导致内部碎片,也就是已分配内存块比用户请求的内存稍大。这是因为内存管理需要在内存块之间维护元数据(例如大小、分配状态),从而浪费一些内存空间。
  4. 释放内存: 当用户调用 free 函数释放已分配的内存时,底层实现将相应的内存块标记为未分配,以便后续 malloc 调用可以再次使用它。
  5. 碎片整理: 随着时间的推移,内存池可能会出现碎片,其中已分配和未分配的内存块交织在一起。一些 malloc 实现会定期执行碎片整理操作,将未分配的内存块合并在一起,以便更好地满足大内存块的请求。
  6. 底层系统调用: 在底层,malloc 的实现通常需要与操作系统内核进行交互,以获取物理内存或虚拟内存的分配和释放权限。这可能涉及到系统调用,如 brkmmap,这些系统调用用于动态分配和释放内存页。

具体的 malloc 实现在不同的编译器和操作系统上可能有所不同。常见的 malloc 实现包括 glibc 中的 malloc、Windows 中的 HeapAlloc 等。这些实现可能采用不同的算法和数据结构来管理内存池,以提高性能和减少碎片。

实验过程中遇到的问题及解决方案

遇到的问题:

在procnum.c文件中直接调用函数procnum(&num)会报错,并且不是因为函数没有定义为procnum(int* num)造成的

解决方案:

将procnum(&num)函数重构为num = procnum()可以解决

实验总结

简单总结一下:实验本身不难,感觉90%的难度都在理解代码,以及各个文件之间的依赖关系和每个函数之间的依赖关系

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1112116.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

嵌入式养成计划-44----QT--消息对话框(QMessageBox)--字体对话框--颜色对话框--文件对话框

一百一十三、消息对话框 &#xff08;QMessageBox&#xff09; 消息对话框给用户提供一个交互式的弹窗&#xff0c;该类提供两种实现版本&#xff0c; 基于属性版本基于静态成员函数版本 基于属性版本 需要用消息对话框这样的类 实例化对象 用该对象调用类里的相关成员函数进…

web:[MRCTF2020]Ez_bypass

题目 点进题目 调整一下 进行代码审计&#xff0c;先看第一段 if(isset($_GET[gg])&&isset($_GET[id])) {$id$_GET[id];$gg$_GET[gg];if (md5($id) md5($gg) && $id ! $gg) {echo You got the first step; get参数传参&#xff0c;后判断md5后的值是否相等&…

2023前端面试题总结

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;web前端面试题库 Html5和CSS3 常见的水平垂直居中实现方案 最简单的方案当然是flex布局 .father {display: flex;justify-content…

手部关键点检测4:Android实现手部关键点检测(手部姿势估计)含源码 可实时检测

目录 1. 前言 2.手部关键点检测(手部姿势估计)方法 (1)Top-Down(自上而下)方法 (2)Bottom-Up(自下而上)方法&#xff1a; 3.手部关键点检测模型训练 4.手部关键点检测模型Android部署 &#xff08;1&#xff09; 将Pytorch模型转换ONNX模型 &#xff08;2&#xff09; …

嘉立创使用技巧

立创社区&#xff1a;电子工程师交流社区_电子发烧友论坛_嘉立创&立创商城旗下专业电子论坛【立创社区】 (szlcsc.com) 嘉立创官网使用教程&#xff1a;立创EDA使用教程 (lceda.cn) 嘉立创是国产软件对新手友好&#xff0c;中国人更懂中国人。下面介绍我在使用中用到的技巧…

【unity小技巧】适用于任何 2d 游戏的钥匙门系统和buff系统——UnityEvent的使用

文章目录 每篇一句前言开启配置门的开启动画代码调用&#xff0c;控制开启门动画 新增CollisionDetector 脚本&#xff0c;使用UnityEvent &#xff0c;控制钥匙和门的绑定多把钥匙控制多个门一把钥匙控制多个门 BUFF系统扩展参考源码完结 每篇一句 人总是害怕去追求自己最重要…

堆-----数据结构

引言 什么是堆&#xff1f;堆是一种特殊的数据结构&#xff08;用数组表示的树&#xff09;。 为什么要使用到堆&#xff1f;比如一场比赛&#xff0c;如果使用擂台赛的方式来决出冠军&#xff08;实力第一&#xff09;&#xff0c;就很难知道实力第二的队伍是什么了。 但是…

Simulink 最基础教程(三)常用模块

3.1源模块 1&#xff09;clock 这个模块的输出是 y(t)t。很多信号都是和时间 t 相关的&#xff0c;例如正弦波信号&#xff0c;可以写成 sin(w*t) 的形式。虽然软件也提供了正弦波模块&#xff0c;但如果用 clock 模块三角运算模块&#xff0c;对初学者而言&#xff0c;也是很好…

QT_day3

完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到新的界面中 如果账号和密码不匹配&#…

科技资讯|2023全球智能手表预估出货1.3亿块,智能穿戴提升AI功能

根据集邦咨询公布的最新报告&#xff0c;受全球经济低迷影响&#xff0c;2023 年全球智能手表出货量预估为 1.3 亿块。苹果以超过 30% 的份额领先&#xff0c;其次是三星&#xff08;接近 10%&#xff09;、华为、Garmin、Fitbit 等。 报告认为苹果、三星和华为等主要智能手表…

智能新零售管理系统哪个好?亿发数字化收银系统提供商,可定制

在数字化时代的背景下&#xff0c;传统收银系统已经无法满足商家不断增加的业务需求。因此&#xff0c;出现了智能门店收银系统&#xff0c;该系统旨在为商家提供更加智能、高效的解决方案&#xff0c;满足商家的个性化需求&#xff0c;帮助中小型商家提高数字化运营能力。 1、…

运筹优化 | Python调用Gurobi求解线性规划 | 代码解析

需要求解的线性规划 from gurobipy import *定义了一个线性松弛问题&#xff0c;并用Gurobi求解 initial_LP Model(initial LP) # 定义变量initial_LP&#xff0c;调用Gurobi的Model&#xff0c;选择Initial Programming&#xff08;整数规划&#xff09;模型 x {} # 创建一个…

TCP/IP模型五层协议

TCP/IP模型五层协议 认识协议 约定双方进行的一种约定 协议分层 降低了学习和维护的成本&#xff08;封装&#xff09;灵活的针对这里的某一层协议进行替换 四/五层协议 五层协议的作用 应用层 应用层常见协议 应用层常见协议概览 基于TCP的协议 HTTP&#xff08;超…

【C++】命名空间和using namespace std的注意事项

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

2022年下半年 软件设计师 上午试卷(22题—40题)

对高级语言源程序进行编译或解释的过程中需要进行语法分析&#xff0c;递归子程序分析属于 &#xff08;22&#xff09; 的分析法。 &#xff08;22&#xff09; A. 自上而下 B. 自下而上 C. 从左至右 D. 从右至左 注意字眼”递归“&#xff0c;自上而下的语法分析方法是一种自…

深入理解 Netty FastThreadLocal

作者&#xff1a;vivo 互联网服务器团队- Jiang Zhu 本文以线上诡异问题为切入点&#xff0c;通过对比JDK ThreadLocal和Netty FastThreadLocal实现逻辑以及优缺点&#xff0c;并深入解读源码&#xff0c;由浅入深理解Netty FastThreadLocal。 一、前言 最近在学习Netty相关的…

【C++面向对象】1. 类、对象

文章目录 【 1. 类 & 对象的定义 】1.1 类的定义1.2 对象的定义 【 2. 类的成员 】2.1 数据成员2.2 成员函数类的内部定义成员函数类的外部定义成员函数成员函数的访问实例 【 3. 类的访问修饰符 】3.1 public 公有成员3.2 private 私有成员3.3 protected 保护成员3.4 继承…

【Excel】WPS单元格快速转换表格字母大小写

使用WPS Office打开表格&#xff0c;选择需要处理的单元格或单元格区域。 依次点击「会员专享」选项卡 —>「智能工具箱」。 再点击「格式」—>「大小写」&#xff0c;选择一种大小写转换方式即可。

测试开发之自动化篇 —— 使用Selenium IDE录制脚本!

今天&#xff0c;我们开始介绍基于开源Selenium工具的Web网站自动化测试。 Selenium包含了3大组件&#xff0c;分别为&#xff1a;1. Selenium IDE 基于Chrome和Firefox扩展的集成开发环境&#xff0c;可以录制、回放和导出不同语言的测试脚本。 2. WebDriver 包括一组为不同…

AI智能视频监控系统解锁新场景:大型音乐节活动视频监控方案

随着近日音乐节的大火&#xff0c;越来越多的人喜欢参加音乐节进行放松娱乐。音乐节通常都会聚集大量人群&#xff0c;为了确保参与者的安全&#xff0c;在音乐节期间设置智能视频监控系统可以帮助管理人员及时发现和应对任何潜在危险或紧急情况&#xff0c;可以保障参与者的生…