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

news2024/11/22 14:18:12

实验目的

加深对进程调度概念的理解,体验进程调度机制的功能,了解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个优先数则按指定的数设置,否则都为10
            setpriority(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 0

expr_3:$(DEPEND)
	$(CC) $(DEPEND) -o $(OBJS)
	
run:$(OBJS)
	./$(OBJS) $(PARA)

clean:
	rm *.o $(OBJS) -rf

总结

本文到这里就结束啦~~

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

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

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

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

 

 

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

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

相关文章

弹幕播放器源码

下 载 地 址 &#xff1a; runruncode.com/php/19761.html 1. 将弹幕播放器的源码上传到服务器。 2. 通过访问你的域名/dmku/install/index.php来进行弹幕库的安装。 3. 修改播放器后台的密码&#xff0c;配置文件为/config.php&#xff0c;并配置json接口。 4. 后台账号为…

国内环境也可以开发好玩的LLM应用 - 环境准备篇

在开发基于LLM(大语言模型)的AI应用前, 我们首先要准备好必要的环境. 主要就是Python环境以及大模型应用开发部署环境. 01 Python开发环境准备 Python开发环境有如下四种, 根据个人喜好选其一即可: 本地安装Python及IDE, 适合学习测试开发; 本地安装Python环境, 使用Jupyter …

享元模式详解

享元模式 1 概述 定义&#xff1a; ​ 运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象的开销&#xff0c;从而提高系统资源的利用率。 2 结构 享元&#xff08;Flyweight &#xff09;模式中存…

【卫星影像三维重建-全流程代码实现】点云Mesh重构

点云—>Mesh模型 1.介绍1.1 背景1.2 效果示意 2 算法实现2.1 依赖库2.2 实验数据2.3 代码实现2.4 实验效果 3.总结 1.介绍 1.1 背景 &#xff08;1&#xff09;本文主要内容是将三维点云&#xff08;离散的三维点&#xff09;进行表面重建生成Mesh网格&#xff0c;之前有篇…

UIKit常用API:Transform

需求 使用Transform系列的API&#xff0c;该API中提供了旋转、平移等功能。其中函数中带make的效果是只变化一次&#xff0c;不带make可变化多次。此外&#xff0c;还有恢复函数&#xff1a;CGAffineTransformIdentity。 代码实现 注意按钮绑定的是同一个响应事件&#xff0…

【AIGC】Mac Intel 本地 LLM 部署经验汇总(CPU Only)

书接上文&#xff0c;在《【AIGC】本地部署 ollama(gguf) 与项目整合》章节的最后&#xff0c;我在 ollama 中部署 qwen1_5-14b-chat-q4_k_m.gguf 预量化模型&#xff0c;在非 Stream 模式下需要 89 秒才完成一轮问答&#xff0c;响应速度实在是太慢&#xff0c;后续需要想办法…

Qt与QWebEngineView 交互-调试窗口-JS拓扑图完整示例参考

1&#xff1a;介绍&#xff1a; Qt与QWebEngineView的交互 简介之前文章解释过&#xff0c;链接在下面 传送门&#xff1a;Qt与QWebEngineView 交互完整示例参考_qt qwebview-CSDN博客 一般在使用这种方式时&#xff0c;可能会出现各种问题而不好调试&#xff0c;如果能够像…

【C++】继承相关(基类与派生类的继承关系以及细节整理)

目录 00.引言 01.继承的定义 02.基类和派生类对象 03.继承中的作用域 04.派生类的默认成员函数 05.友元、静态成员 00.引言 继承是面向对象编程中的一个重要概念&#xff0c;它的作用是创建一个新的类&#xff0c;该类可以从一个已存在的类&#xff08;父类/基类&#x…

sipeed 的 MaixCam显示图片

WiFi联网后&#xff0c;把固件升级到最新 一根tpyc-c连接线为MaixCam供电&#xff0c;点击液晶屏settings 在WiFi中设置确保联网&#xff0c;在更新MaixPy中升级固件 可以选择国内源加速&#xff0c;将固件升级到最新版 MaixVision的操作 1&#xff0c;在MaixVision左下角…

谷歌Gboard应用的语言模型创新:提升打字体验的隐私保护技术

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

C语言 | Leetcode C语言题解之第87题扰乱字符串

题目&#xff1a; 题解&#xff1a; struct HashTable {int key;int val;UT_hash_handle hh; };void modifyHashTable(struct HashTable** hashTable, int x, int inc) {struct HashTable* tmp;HASH_FIND_INT(*hashTable, &x, tmp);if (tmp NULL) {tmp malloc(sizeof(st…

【数据结构与算法 刷题系列】合并两个有序链表

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;数据结构与算法刷题系列&#xff08;C语言&#xff09; 目录 一、问题描述 二、解题思路详解 合并两个有序链表的思路 解题的步…

HTML飘落的花瓣

目录 写在前面 HTML​​​​​​​简介 完整代码 代码分析 系列推荐 写在最后 写在前面 本期小编给大家推荐HTML实现的飘落的花瓣&#xff0c;无需安装软件&#xff0c;直接下载即可打开~ HTML​​​​​​​简介 HTML&#xff08;Hypertext Markup Language&#xff…

【Linux】文件描述符和重定向

目录 一、回顾C文件 二、系统文件I/O 2.1 系统调用 open 2.2 标志位传参 2.3 系统调用 write 2.4 文件描述符fd 2.5 struct file 2.6 fd的分配规则 2.7 重定向 2.7.1 基本原理&#xff1a; 2.7.2 系统调用 dup2 2.8 标准错误 一、回顾C文件 文件 内容 属性 对…

阿里云OSS配置跨域及域名访问

1、配置跨域 进入对象存储OSS–>OSS存储桶–>数据安全–>跨域设置–>创建规则 2、配置跨域 Etag x-oss-request-id3、配置结果如下 4、数据源配置 切换到数据管理–>静态页面 配置根页面 保存结果如下 5、配置域名访问 绑定域名 添加txt记录 验证绑定 …

【CSP CCF记录】202109-2 非零段划分

题目 过程 思路 参考&#xff1a;http://t.csdnimg.cn/XRKTm STL库用法 unique用法 unique是STL中很实用的函数之一&#xff0c;需要#include&#xff08;感谢各位提醒&#xff09;&#xff0c;下面来简单介绍一下它的作用。 unique的作用是“去掉”容器中相邻元素的重复…

手机配置在线检测工具微信小程序源码

手机配置在线检测工具微信小程序源码&#xff0c;这是一款升级版检测工具&#xff0c;自动检测手机真伪,序列号等。另外还可以给手机检测各项功能是否正常。 由于能检测的项目太多,所以大家到时候自行研究吧。另外支持多做流量主模式,还有外卖CPS,和友情小程序推荐等&#xff…

Unity自定义动画-Animation动画数据-How is “fileIDToRecycleName“ generated

一般美术和程序分工明确的项目 fbx确实是和动画一一对应的&#xff1b; 但一些独立&#xff0c;或者小工作室的项目&#xff0c;就没法保证了&#xff0c;关键还是在于 Unity的 .meta 目录 查找和对比了一下 .fbx 和 .meta&#xff1a; 缓存和不缓存Animation 具体的Animat…

天诚AIoT无线联网智能门锁即将亮相成都安博会、永康门博会

5月上旬&#xff0c;对于江苏新巢天诚智能技术有限公司&#xff08;以下简称“天诚”&#xff09;而言&#xff0c;依旧忙得如火如荼。随着各地人才公寓、公租房、智慧校园类智慧通行与租住新项目的实施、落地与服务&#xff0c;天诚也不忘初心&#xff0c;携全新升级的AIoT全场…

DEV--C++小游戏(吃星星(0.5))

目录 吃星星&#xff08;0.5&#xff09; 该版本简介 DEV--C小游戏(吃星星(0.1)) DEV--C小游戏(吃星星(0.2)) 分部代码 头文件 命名空间变量&#xff08;增&#xff09; 副函数&#xff08;新&#xff0c;增&#xff09; 清屏函数 打印地图函数&#xff08;增&…