操作系统实战(三)(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;但你的行囊有一…

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…

从零开始搭建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后点…

嫁接打印的技术要点

所谓嫁接打印&#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…

使用FFmpeg处理RTSP视频流并搭建RTMP服务器实现图片转直播全流程

目录 一、FFmpeg安装与配置教程二、搭建并配置Nginx RTMP服务器三、从RTSP视频流提取帧并保存为图片四、将图片序列转换为视频五、将视频推送为直播流六、将图片序列推送为直播流 在实时音视频领域&#xff0c;我们经常需要处理从各种源&#xff08;如摄像头&#xff09;获取的…

Yolov8目标检测——在Android上部署Yolov8 tflite模型

1. 简介 YOLOv8 是一种用于目标检测的深度学习模型&#xff0c;它是 YOLO&#xff08;You Only Look Once&#xff09;系列的最新版本之一。YOLO 系列因其高效和准确性而在计算机视觉领域非常受欢迎&#xff0c;特别是在需要实时目标检测的应用中&#xff0c;如视频监控、自动…

Jmeter中线程组介绍

1.线程数的意义 Jmeter采用了线程来模拟用户&#xff0c;即1个线程代表1个用户&#xff0c;线程可以简单理解为计算机处理任务时的一个具体执行人。 一个任务可以由多个人&#xff08;线程&#xff09;共同完成&#xff0c;也可以由一个人&#xff08;线程&#xff09;来完成&a…

Fastapi+docker+tortoise-orm+celery

因为项目是后期引入celery,所以导致构建docker的时候只有fastapi的项目&#xff0c;celery的重启比较麻烦 1.docker安装celery pip install celery安装celery的时候注意python版本与celery版本的适配&#xff0c;有些celery的版本不支持python的版本&#xff0c;具体的版本请看…

网络基础-ICMP协议

ICMP&#xff08;Internet Control Message Protocol&#xff0c; Internet控制消息协议&#xff09; ICMP协议是IP协议的辅助协议&#xff0c;用于在IP网络上发送控制消息&#xff0c;它通常被用于诊断网络故障、执行网络管理任务以及提供一些错误报告&#xff1b;对于收集各…

深入理解线程的两阶段终止模式:确保线程安全退出

序言 在多线程编程中&#xff0c;线程的安全退出是一个重要的问题。在实际应用中&#xff0c;我们经常需要确保线程在退出时能够完成必要的清理工作&#xff0c;同时避免因资源泄漏或状态不一致而导致的问题。线程的两阶段终止模式是一种解决这个问题的有效方法。本文将深入探…