操作系统实战(三)(linux+C语言实现)

实验目的

加深对进程调度概念的理解,体验进程调度机制的功能,了解Linux系统中进程调度策略的使用方法。 练习进程调度算法的编程和调试技术。

实验说明

1.在linux系统中调度策略分为3种

  • SCHED_OTHER:默认的分时调度策略,值为0
  • SCHED_FIFO:先进先出调度,值为1
  • SCHED_RR:轮转法调度,值为2

理解关键点:

  • 不同调度策略之间本身的优先级不同,FIFO调度策略优先级最高,其次是轮转法调度法,最后是默认分时调度策略(FIFO的所有程序相比于分时程序优先级更高)
  • 分时调度策略的优先级指的是动态优先级。动态优先级=nice值+进程运行时间值来决定的。对于FIFO、RR来说只是决定nice值的方式不一样

2.设置进程调度策略的系统调用语法

int sched_setscheduler(pid_t pid,int policy,const struct sched_param *sp);
  • pid:进程号
  • policy:三种调度策略之一
  • sp:调度参数结构指针,里面有调度优先数

理解关键点:

  • 设置进程的调度策略时,输入的参数肯定有:进程标识pid、调度策略policy。同时考虑到确定进程调度策略后要马上根据进程优先级来确定进程实际的执行次序,所以在设置进程调度策略时需要传递进程优先级
  • sched_setscheduler函数在sched.h头文件当中
  • 执行成功返回0

3.获取进程调度策略的系统调用语法

int sched_getscheduler(pid_t pid);
  • pid 进程号
  • 返回值: 进程当前的调度策略对应的数值

4.获取进程动态优先数的系统调用语法

int getpriority(int which,int who);

理解关键点: 

1、which代表设置的对象是什么类型的(进程、进程组、用户)

2、which的值可以是:

  • 进程 PRIO_PROCESS
  • 进程组 PRIO_PGRP
  • 用户 PRIO_USER

3、who的值是:设置对象类型下的标号(进程号或组号或用户号)

4、返回值:所有匹配进程中的最高优先级(本次实验是查找进程pid,所以结果只有一个)

5.设置进程动态优先数的系统调用语法

int setpriority(int which,int who,int prio);

理解关键点:

1、which代表设置的对象,which的值可以是

  • 进程 PRIO_PROCESS
  • 进程组 PRIO_PGRP
  • 用户 PRIO_USER

2、who表示对应查找对象集合中的具体实例 

3、prio设置的是要设置的进程优先级

4、返回值:所有匹配进程中的最高优先级

实例程序 

#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <sys/time.h>
#include <sys/resource.h>
int main(int argc, char *argv[])
{int i,j,status;int pid[3]; //存放进程号struct sched_param p[3]; //设置调度策略时使用的数据结构for(i=0; i<3;i++){//循环创建3 个子进程if((pid[i]=fork()) >0){//取进程优先数放在调度策略数据结构中p[i].sched_priority = (argv[i+1] != NULL) ? atoi(argv[i+1]):10;//父进程设置子进程的调度策略.如果命令行第4,5,6 参数指定了3个策略值则按指定的数设置,否则都为默认策略sched_setscheduler(pid[i],(argv[i+4] != NULL) ? atoi(argv[i+4]) : SCHED_OTHER,&p[i]);//父进程设置子进程的优先数,如果命令行第1,2,3 参数指定了3个优先数则按指定的数设置,否则都为10setpriority(PRIO_PROCESS,pid[i],(argv[i+1] != NULL) ? atoi(argv[i+1]):10);}//各子进程循环报告其优先数和调度策略else{sleep(1);//每隔1 妙报告一次进程号和优先级for(i=0; i<10; i++){printf("Child PID = %d priority = %d\n",getpid(),getpriority(PRIO_PROCESS,0));sleep(1);}exit( EXIT_SUCCESS);}}//父进程报告子进程调度策略后先行退出printf("My child %d policy is %d\n",pid[0],sched_getscheduler(pid[0]));printf("My child %d policy is %d\n",pid[1],sched_getscheduler(pid[1]));printf("My child %d policy is %d\n",pid[2],sched_getscheduler(pid[2]));return EXIT_SUCCESS;
}

运行结果 

结果解释 

1、父进程先运行结束:父进程并未用wait等待子进程。同时对子进程使用sleep函数来休眠,所以父进程一定先运行结束并汇报出子进程的调度策略

2、优先数小的进程先执行:按照正常逻辑推理应该是优先数小的进程先执行,但是对于现在的多核CPU来说不同优先级的三个子进程仍然几乎可以说是在并行的(不是并发),所以实际效果是三进程顺序不太固定。但是可以看到优先级为18的进程不可能是第一个被调度的,说明优先级仍然在影响对CPU资源的占用

3、进程调度策略的修改:由于没有开sudo管理员权限,所以不允许对进程的调度策略进行修改

本次实验代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sched.h>
#include <sys/time.h>
#include <sys/resource.h>
static int priority1=0;
static int priority2=0;
//加信号,只对子进程
void add(int sig)
{priority2++;
}
//减信号,只对子进程
void minus(int sig)
{priority2--;
}
int main(int argc, char *argv[])
{//绑定信号signal(SIGINT,add);signal(SIGTSTP,minus);//定义数组存储父子进程的pid值int pid[2];//父进程运行if((pid[1]=fork())>0){pid[0] = getpid();struct sched_param p[2];//得到argv参数int priority1=atoi(argv[1]);int priority2=atoi(argv[2]);//父进程初始化父子进程优先级以及调度策略for(int i=0; i<2;i++){//取进程优先数放在调度策略数据结构中p[i].sched_priority = (argv[i+1] != NULL) ? atoi(argv[i+1]):10;//父进程设置自己和子进程的调度策略sched_setscheduler(pid[i],(argv[i+3] != NULL) ? atoi(argv[i+3]):SCHED_OTHER,&p[i]);//父进程设置自己和子进程的优先数setpriority(PRIO_PROCESS,pid[i],(argv[i+1] != NULL) ? atoi(argv[i+1]):10);}//父进程循环调整优先级int parentPid=getpid();while(1){//输出进程号printf("parent pid = %d\n",parentPid);//输出优先级printf("parent process priority = %d\n",getpriority(PRIO_PROCESS,parentPid));//输出调度策略printf("parent process scheduler = %d\n",sched_getscheduler(parentPid));//设置进程的优先级setpriority(PRIO_PROCESS,parentPid,priority1);sleep(5);}}else{int childPid=getpid();while(1){//输出进程号printf("child pid = %d\n",childPid);//输出当前运行进程的优先级(也就是子进程的优先级)printf("child process priority = %d\n",getpriority(PRIO_PROCESS,0));//输出调度策略printf("child process scheduler = %d\n",sched_getscheduler(childPid));//设置进程的优先级setpriority(PRIO_PROCESS,childPid,priority2);sleep(5);}}
}

运行结果

 

结果分析 

1、一开始设定父进程优先级为6,子进程为4。打入一个中断后,父子进程中便会是子进程先运行。(中断会让所有进程都去执行信号处理函数,然后再统一开始顺序执行进程)

2、后续利用自定义add方法能够让子进程的优先级变为8,此时大部分情况下,会先调度父进程后调度子进程(如何错乱了利用中断信号可以恢复正确的顺序)

3、有时候进程调度的顺序不是完全按照设定优先级进行的,为了防止部分进程恶意抢占所有资源,并且其他的进程随着时间也会增加静态优先级,从而获得更高的优先级

 makefile文件

# DEPEND   代替  依赖文件
# CC       代替  gcc
# CFLAGS   代替  编译命令
# PARA     代替  参数
# OBJS     代替 目标文件DEPEND=expr_3.c
OBJS=expr_3
CC=gcc
CFLAGS=-o
PARA=6 4 0 0expr_3:$(DEPEND)$(CC) $(DEPEND) -o $(OBJS)run:$(OBJS)./$(OBJS) $(PARA)clean:rm *.o $(OBJS) -rf

总结

本文到这里就结束啦~~

本篇文章重点在于利用linux系统的完成操作系统的实验,巩固课堂知识

本篇文章的撰写+实验代码调试运行+知识点细致化学习,共花了本人3h左右的时间

如果仍有不够希望大家多多包涵~~如果觉得对你有帮助,辛苦友友点个赞哦~

知识来源:山东大学操作系统实验三、山东大学《操作系统原理实用实验教程》张鸿烈老师编著

 

 

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

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

相关文章

Keycloak实战+spring boot

标题 前言项目搭建前言 最近项目中使用keycloak,为了更好的上手,我先本地Windows搭建一套demo 项目搭建 我本地jdk版本号为: 通过网上查询一些资料查看,jdk1.8对应的keycloak版本为:15的版本,但是没有找到,我只能下载如下: 通过码云我找到了具体的版本号,开始下…

国内注册Claude 3流程

国内注册Claude 3流程 Claude 3是什么注册过程准备国外IP节点准备谷歌账号或者邮箱准备接码平台接码平台WildCard输入验证码继续注册 使用聊天功能识图功能文件解析编码能力 Cloud 3 已经推出两个月了&#xff0c;当时可是轰动一时&#xff0c;但是其并不对国内开放&#xff0c…

Go 语言并发编程初体验:简洁高效

文章目录 前言GoLang 并发编程基本概念进程与线程线程和协程并行与并发GoLang的协程机制 GoLang 并发实践案例需求传统方式实现使用 goroutines 实现并发goroutine 如何通信channel 使用注意事项 总结 前言 Go语言是谷歌推出的一种的编程语言&#xff0c;可以在不损失应用程序…

Java通过百度地图API获取定位-普通IP定位

项目中有一个登录邮箱提醒的功能&#xff0c;需要根据IP地址获取定位信息&#xff0c;从而更好地提示用户账号登录的所在地。为此&#xff0c;花费了一些时间来实现这个功能。 在CSDN搜索了一下&#xff0c;发现关于获取定位的文章说明都不够详细&#xff0c;于是决定自己创作一…

【C++ 内存管理】深拷贝和浅拷贝你了解吗?

文章目录 1.深拷贝2.浅拷贝3.深拷贝和浅拷贝 1.深拷贝 &#x1f34e; 深拷⻉: 是对对象的完全独⽴复制&#xff0c;包括对象内部动态分配的资源。在深拷⻉中&#xff0c;不仅复制对象的值&#xff0c;还会复制对象所指向的堆上的数据。 特点&#xff1a; &#x1f427;① 复制对…

1.理解机器学习

本文参考于&#xff1a;https://hands1ml.apachecn.org/1/ 大多数人听到“机器学习”&#xff0c;往往会在脑海中勾勒出一个机器人&#xff1a;一个可靠的管家&#xff0c;或是一个可怕的终结者&#xff0c;这取决于你问的是谁。但是机器学习并不是未来的幻想&#xff0c;它已经…

【吃透Java手写】3-SpringBoot-简易版-源码解析

【吃透Java手写】SpringBoot-简易版-源码解析 1 SpringbootDemo2 准备工作2.1 Springboot-my2.1.1 依赖2.1.2 SpringBootApplication2.1.3 SJBSpringApplication2.1.3.1 run方法 2.2 Springboot-user2.2.1 依赖2.2.2 UserController2.2.3 UserApplication 2.3 分析run方法的逻辑…

第二章 checkpoint机制 - 介绍

Checkpoint介绍 1、介绍 PostgreSQL基于DRAMHDD/SSD两层存储架构&#xff0c;所有读写都在DRAM中进行。由于数据写大部分都是随机的&#xff0c;为提高数据库性能&#xff0c;通过写前日志WAL将所有修改都记录到日志中&#xff0c;事务提交时&#xff0c;将日志持久化到磁盘即…

Java入门基础学习笔记12——变量详解

变量详解&#xff1a; 变量里的数据在计算机中的存储原理。 二进制&#xff1a; 只有0和1&#xff0c; 按照逢2进1的方式表示数据。 十进制转二进制的算法&#xff1a; 除二取余法。 6是110 13是1101 计算机中表示数据的最小单元&#xff1a;一个字节&#xff08;byte&…

通俗的理解网关的概念的用途(一)

网关这个概念最早使用于网络&#xff0c;但在当今的智能设备/产品界中&#xff0c;硬生生的被产品人也搞出来一个“网关”的概念&#xff0c;这让早期的咱们这些只知道网络中的网关的人&#xff0c;听得稀里糊涂的。比如智能门锁、安防摄像头等&#xff0c;在产品的使用和介绍中…

java JMH 学习

JMH 是什么&#xff1f; JMH&#xff08;Java Microbenchmark Harness&#xff09;是一款专用于代码微基准测试的工具集&#xff0c;其主要聚焦于方法层面的基准测试&#xff0c;精度可达纳秒级别。此工具由 Oracle 内部负责实现 JIT 的杰出人士编写&#xff0c;他们对 JIT 及…

服务号转订阅号的操作步骤(吐血整理)

服务号和订阅号有什么区别&#xff1f;服务号转为订阅号有哪些作用&#xff1f;我们知道&#xff0c;公众号分为服务号和订阅号两种&#xff0c;服务号只能企业才可以申请&#xff0c;订阅号是企业和个人都可以申请。其中最大的区别是服务号一个月只能发送4次群发&#xff0c;但…

shopro商城 源码搭建/部署/上线/运营/售后/更新

基于Fastadmin和Uniapp进行开发的多平台&#xff08;微信公众号、微信小程序、H5网页、Android-App、IOS-App&#xff09;购物商城&#xff0c;拥有强大的店铺装修、自定义模板、路由同步、多端支付&#xff08;微信&#xff0c;支付宝&#xff09;、多规格商品、运费模板、多地…

我在洛杉矶采访到了亚马逊云全球首席信息官CISO(L11)!

在本次洛杉矶举办的亚马逊云Re:Inforce全球安全大会中&#xff0c;小李哥作为亚马逊大中华区开发者社区和自媒体代表&#xff0c;跟着亚马逊云安全产品团队采访了亚马逊云首席信息安全官(CISO)CJ Moses、亚马逊副总裁Eric Brandwine和亚马逊云首席高级安全工程师Becky Weiss。 …

【学习AI-相关路程-工具使用-自我学习-Ubuntucudavisco-开发工具尝试-基础样例 (2)】

【学习AI-相关路程-工具使用-自我学习-cuda&visco-开发工具尝试-基础样例 &#xff08;2&#xff09;】 1、前言2、环境说明3、总结说明4、工具安装0、验证cuda1、软件下载2、插件安装 5、软件设置与编程练习1、创建目录2、编译软件进入目录&创建两个文件3、编写配置文…

可微分矢量图形光栅化用于编辑和学习

图1. 我们引入了一种通过反向传播将光栅和矢量域联系起来的矢量图形可微分光栅化器。可微分光栅化实现了许多新颖的矢量图形应用。&#xff08;a&#xff09;在几何约束下&#xff0c;通过局部优化图像空间度量&#xff08;如不透明度&#xff09;来实现交互式编辑。&#xff0…

如何使用vue脚手架创建项目

前言 使用vue搭建项目的时候&#xff0c;我们可以通过对应的cmd命令去打开脚手架&#xff0c;然后自己配置对应的功能插件 说明&#xff1a; 要使用Vue脚手架创建项目&#xff0c;你需要先确保你已经安装了Node.js和npm&#xff08;Node.js的包管理器&#xff09;。然后&#…

uniapp 版本检查更新

总体来说uniapp的跨平台还是很不错的&#xff0c;虽然里面各种坑要去踩&#xff0c;但是踩坑也是开发人员的必修课和成长路。 这不&#xff0c;今天就来研究了一下版本检查更新就踩到坑了。。。先来看看检查更新及下载、安装的实现。 先来看看页面&#xff1a; 从左到右依次为…

CSRF、XSS攻防原理及解决方案

一、CSRF CSRF 全称叫做&#xff0c;跨站请求伪造(Cross—Site Request Forgery)&#xff0c;顾名思义&#xff0c;攻击者盗用了你的身份&#xff0c;以你的名义发送恶意请求&#xff0c;对服务器来说这个请求是完全合法的&#xff0c;但是却完成了攻击者所期望的一个操作&…

bbr 是真不行

bbr 作为 mimd 实例如何收敛到公平请看 瓶颈带宽的公平收敛&#xff0c;但这只是公平收敛&#xff0c;并不是 buffer 收敛。 上午跟朋友讨论了一个有趣的问题&#xff0c;感觉有必要揭露一下 bbr 的 buffer 不收敛。若不是有 probertt&#xff0c;多流共享瓶颈链路场景下&…