操作系统实战(三)(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://www.mzph.cn/pingmian/9918.shtml

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

相关文章

HC-05的简介与使用

蓝牙概述 蓝牙&#xff08;Bluetooth&#xff09;是一种用于无线通信的技术标准&#xff0c;允许设备在短距离内进行数据交换和通信。它是由爱立信&#xff08;Ericsson&#xff09;公司在1994年推出的&#xff0c;以取代传统的有线连接方式&#xff0c;使设备之间能够实现低功…

机器学习-L1正则/L2正则

机器学习-L1正则/L2正则 目录 1.L1正则 2.L2正则 3.结合 1.L1正则 L1正则是一种用来约束模型参数的技术&#xff0c;常用于机器学习和统计建模中&#xff0c;特别是在处理特征选择问题时非常有用。 想象一下&#xff0c;你在装备行囊准备去旅行&#xff0c;但你的行囊有一…

DNS-域名系统

DNS-域名系统 1.工作逻辑 DNS&#xff08;域名系统&#xff09;是互联网的一项核心服务&#xff0c;它负责将人类可读的网址&#xff08;例如 www.google.com&#xff09;转换为计算机可理解的 IP 地址&#xff08;例如 172.217.0.4&#xff09;。下面是 DNS 的基本工作过程:…

JavaScript Web API 的概念

JavaScript Web API 是浏览器提供的一套可以用来操作和交互网页的接口集合。它允许开发者通过JavaScript代码来访问和操作浏览器的功能&#xff0c;例如DOM操作、事件处理、发送HTTP请求等。 以下是一些常见的JavaScript Web API&#xff1a; DOM API&#xff1a;允许开发者通…

L2-052 吉利矩阵 - java

L2-052 吉利矩阵 代码长度限制 16 KB 时间限制 1000 ms 内存限制 64 MB 栈限制 8192 KB 题目描述&#xff1a; 所有元素为非负整数&#xff0c;且各行各列的元素和都等于 7 的 33 方阵称为“吉利矩阵”&#xff0c;因为这样的矩阵一共有 666 种。 本题就请你统计一下&#xff0…

CAP与BASE分布式理论

一、分布式理论 1.CAP理论 CAP理论是说对于分布式数据存储&#xff0c;最多只能同时满足一致性&#xff08;C&#xff0c;Consistency&#xff09;、可用性&#xff08;A&#xff0c; Availability&#xff09;、分区容忍性&#xff08;P&#xff0c;Partition Tolerance&…

debian testing (预计13版本)wps字体无法正常显示

背 景 本人使用debian办公&#xff0c;原来使用的是debian 12,由于“生命不息&#xff0c;折腾不止“&#xff0c;终于将稳定版的debian 12升级为testing. 结果发现&#xff0c;debian 12能够正常使用的wps存在部分字体无法正常显示&#xff0c;经研究发现&#xff0c;原来是w…

(三十九)第 6 章 树和二叉树(二叉树的三叉链表存储)

1. 背景说明 2. 示例代码 1) errorRecord.h // 记录错误宏定义头文件#ifndef ERROR_RECORD_H #define ERROR_RECORD_H#include <stdio.h> #include <string.h> #include <stdint.h>// 从文件路径中提取文件名 #define FILE_NAME(X) strrchr(X, \\) ? strrc…

JINGWHALE 虚拟现实物质与空间理论 —— 全息世界

JINGWHALE 对此论文相关未知以及已知概念、定理、公式、图片等内容的感悟、分析、创新、创造等拥有作品著作权。未经 JINGWHALE 授权&#xff0c;禁止转载与商业使用。 一、虚拟现实物质与空间理论 物质是由离散的奇点JING粒子&#xff0c;依据不同的维度粒度&#xff0c;通过…

uniapp开发微信小程序,选择地理位置uni.chooseLocation

<view click"toCommunity">点击选择位置</view>toCommunity() {const that thisuni.getSetting({success: (res) > {const status res.authSetting// 如果当前设置是&#xff1a;不允许&#xff0c;则需要弹框提醒客户&#xff0c;需要前往设置页面…

EXPLORER - Stone Age

一个程式化的包,包含史前建筑、巨石结构、角色、自然资产、工具和各种道具,可以添加到你的游戏中。 包装内容: + 570 资产。 男性和女性角色,包括数十件服装、皮肤和配饰。 - 8 - 预制角色变体 安装后即可直接使用。 - 15 - 包括动画(8个男性动画和7个女性动画),与Mecan…

Swift 函数

函数 一、函数的定义与调用二、函数参数与返回值1、无参数函数2、多参数函数3、无返回值函数4、多重返回值函数5、可选元组返回类型6、隐式返回的函数三、函数参数标签和参数名称1、指定参数标签2、忽略参数标签3、默认参数值4、可变参数5、输入输出参数四、函数类型1、使用函数…

MATLAB算法实战应用案例精讲-【数模应用】信度分析(附python和R语言代码实现)

目录 算法原理 信度系数 信度分析和真分数测量理论 内在信度和外在信度

从零开始搭建Ubuntu CTF-pwn环境

下面就将介绍如何从零搭建一个CTF-pwn环境&#xff08;由于学习仍在进行&#xff0c;故一些环境如远程执行环境还没有搭建的经历&#xff0c;如今后需要搭建&#xff0c;会在最后进行补充&#xff09; 可以在ubuntu官方网站上下载最新的长期支持版本:(我下载的是22.04版本) h…

指针系列三

文章目录 1.字符指针&#xff1a;2.数组指针&#xff1a;3.二维数组传参的本质4.函数指针变量typedef 关键字 5.函数指针数组6.转移表 1.字符指针&#xff1a; 字符指针&#xff0c;也称为字符串指针&#xff0c;是指向内存中的字符或字符串的指针。 在C语言中&#xff0c;字符…

【树莓派4B】如何用树莓派的串口发送数据给单片机

文章目录 查看路由器中的树莓派IProot连接打开vnc远程桌面服务打开win的远程桌面软件输入IP和端口串口发送数据硬件连接树莓派发送 查看路由器中的树莓派IP root连接 打开vnc远程桌面服务 vncserver :1打开win的远程桌面软件 输入IP和端口 192.168.3.33:1输入密码qwer1234后点…

【找子序列“happy”,可不连续型,双指针】

不是每段相遇都有个美好的结局&#xff0c;阿米娅。有很多故事戛然而止&#xff0c;有很多故事让人辗转反侧&#xff0c;另一些......最后只能变成一声长长的叹息。在没有尽头的荒原上&#xff0c;人们相逢&#xff0c;然后走散&#xff0c;但在错身而过的那个瞬间......没有人…

嫁接打印的技术要点

所谓嫁接打印&#xff0c;是一种增减材混合制造的方式。它将已成形的模具零件当作基座&#xff0c;在此基础上“生长”出打印的零件。其中基座通常采用传统加工方式制造&#xff0c;而打印部分则使用专用的金属粉末&#xff0c;通过 3D 打印技术成型。 嫁接打印之所以备受欢迎&…

Docker + Django跨域解决方案

什么是Django Django 是一个开源的高级 Python Web 框架&#xff0c;它鼓励快速开发并遵循可重用和可维护的实践。Django 是在 MTV&#xff08;模型-模板-视图&#xff09;模式的基础上设计的&#xff0c;这个模式类似于但不同于 MVC&#xff08;模型-视图-控制器&#xff09;模…

centos安装mysql-client

直接安装&#xff1a; yum install mysql-community-client报了错误No package mysql-community-client available. 原因&#xff1a;CentOS/RHEL系统默认的软件源中并不包含MySQL软件包&#xff0c;需要通过添加第三方存储库来获取MySQL相关软件 添加源 安装MySQL官方的Yum…