16 - 初探Linux进程调度

---- 整理自狄泰软件唐佐林老师课程

查看所有文章链接:(更新中)Linux系统编程训练营 - 目录

文章目录

  • 1. 初探Linux进程调度
    • 1.1 Linux系统调度
    • 1.2 进程调度原理
    • 1.3 Linux系统调度策略
    • 1.4 进程调度实验设计
      • 1.4.1 实验目标
      • 1.4.2 实验设计
    • 1.5 实验需解决的问题
      • 1.5.1 “固定”时间工作量估算
      • 1.5.2 获取/改变进程调度策略
      • 1.5.3 记录进程运行后产生数据
      • 1.5.4 图形化数据显示与分析
    • 1.6 编程实验:进程调度实验
      • 1.6.1 SCHED_OTHER
      • 1.6.2 SCHED_RR
      • 1.6.3 SCHED_FIFO

1. 初探Linux进程调度

已知:父进程创建子进程后,父子进程同时运行

  • 问题:如果计算机只有一个处理器,父子进程以什么方式同时执行?

1.1 Linux系统调度

  • 内核具有进程调度的能力,多个进程可同时运行
  • 微观上,处理器同一时间只能执行一个进程
  • 同时运行多个进程时,每个进程都会获得适当的执行时间片
  • 当执行时间片用完时,内核调度下一个进程执行

1.2 进程调度原理

  • n个进程(n >= 2)同时位于内存中
  • 处理器执行完每个进程,每个进程拥有一个时间片
  • 时间片用完,通过时钟中断完成进程切换(调度)
    在这里插入图片描述

1.3 Linux系统调度策略

  • 普通调度策略
    • SCHED_OTHER:Linux默认的调度策略,也被称为CFS(Completely Fair Scheduler),给每个进程动态计算优先级,根据优先级和进程执行的历史记录来确定下一个执行的进程。
  • 实时调度策略
    • SCHED_FIFO:基于优先级顺序调度进程,并在一个进程获得CPU时一直执行,直到进程主动释放。
    • SCHED_RR:基于“时间片轮转”的调度策略,给每个进程设置一个固定的时间片,并按照优先级顺序对进程进行轮流调度。

1.4 进程调度实验设计

1.4.1 实验目标

  1. 验证 同一时刻只有一个进程在执行
  2. 验证 不同调度策略,进程执行的连续性不同

1.4.2 实验设计

  1. n个进程同时运行,统计各个进程的执行时刻
  2. 进程运行方式:
    • 每个slice时间记录如下值:进程编号,当前时间值,完成度
    • 在total时间后结束运行,并输出记录的数据
    • 通过记录的数据分析进程调度策略

1.5 实验需解决的问题

  • 如何让进程每次“固定”工作slice时间(单位毫秒)?
  • 如何获取和改变进程的调度策略?
  • 如何记录数据并输出数据(需要保存数据)?
  • 如何图形化显示数据?

1.5.1 “固定”时间工作量估算

  • Linux中的时间获取

在这里插入图片描述
在这里插入图片描述

1.5.2 获取/改变进程调度策略

在这里插入图片描述

  • chrt命令简介
    Linux系统中可以使用chrt命令来查看、设置一个进程的优先级和调度策略
  • 命令用法

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

1.5.3 记录进程运行后产生数据

在这里插入图片描述

1.5.4 图形化数据显示与分析

在这里插入图片描述

1.6 编程实验:进程调度实验

【参看链接】:16 - 初探Linux进程调度

  • taskset实验

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 进程调度实验
#include <sys/wait.h>
#include <sys/resource.h>
#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <fcntl.h>#define NLOOP_FOR_ESTIMATION 1000000000UL
#define NSECS_PER_MSEC 1000000UL
#define NSECS_PER_SEC 1000000000UL#define DiffNS(begin, end) ((end.tv_sec - begin.tv_sec) * NSECS_PER_SEC \+ (end.tv_nsec - begin.tv_nsec))static unsigned long g_load_per_slice;
static struct timespec g_time_begin;static unsigned long estimate_loops_per_msec() // 1ms有多少次循环
{struct timespec begin = {0};struct timespec end   = {0};unsigned long i = 0;clock_gettime(CLOCK_MONOTONIC, &begin);while (i < NLOOP_FOR_ESTIMATION) i++;clock_gettime(CLOCK_MONOTONIC, &end);return NLOOP_FOR_ESTIMATION / (DiffNS(begin, end) / NSECS_PER_MSEC);
}static inline void work()
{unsigned int i = 0;// g_load_per_slice 每个时间片的循环次数// 经过 1 个时间片的循环次数后返回,模拟工作 1 个时间片while (i < g_load_per_slice) i++;
}static void test(int id, struct timespec* tss, int nrecord)
{struct timespec ts = {0};char buf[128] = {0};int fd = -1;int i = 0;// nrecord 记录的时间片数,也就是进程要执行的总时间for (i = 0; i < nrecord; i++) {work();clock_gettime(CLOCK_MONOTONIC, tss + i);}sprintf(buf, "./%d-proc.log", id);printf("%s\n", buf);fd = open(buf, O_WRONLY | O_CREAT | O_TRUNC);if (fd != -1) {for (i = 0; i < nrecord; i++) {sprintf(buf, "%d\t%ld\t%d\n",id,DiffNS(g_time_begin, tss[i]) / NSECS_PER_MSEC,(i + 1) * 100 / nrecord);write(fd, buf, strlen(buf));}}close(fd);
}int main(int argc, char* argv[])
{int nproc = atoi(argv[1]); // 创建多少个进程int total = atoi(argv[2]); // 每个进程需要执行的时间int slice = atoi(argv[3]); // 时间片int nrecord = total / slice;// 申请记录 nrecord 条记录的 logbufstruct timespec* logbuf = malloc(nrecord * sizeof(*logbuf));pid_t* pids = malloc(nproc * sizeof(*pids));total = total / slice * slice;if (logbuf && pids) {int i = 0;int n = 0;printf("nproc = %d\n", nproc);printf("total = %d\n", total);printf("slice = %d\n", slice);printf("SCHED_OTHER = %d\n", SCHED_OTHER);printf("SCHED_FIFO  = %d\n", SCHED_FIFO);printf("SCHED_RR    = %d\n", SCHED_RR);printf("Begin estimate work load per slice...\n");g_load_per_slice = estimate_loops_per_msec() * slice; // 每个时间片的循环次数printf("End ==> g_load_per_slice = %ld\n", g_load_per_slice);clock_gettime(CLOCK_MONOTONIC, &g_time_begin); // 统计的起始时间for (i = 0; i < nproc; i++) {pids[i] = fork();if (pids[i] < 0) {int j = 0;while (j < n) {kill(pids[j++], SIGKILL); // 杀死创建成功的子进程}printf("Process create error...\n");break;} else if (pids[i] == 0) {int sched = sched_getscheduler(0);int pri = getpriority(PRIO_PROCESS, 0);printf("task %d ==> schedule policy: %d\n", i, sched);printf("task %d ==> schedule priority: %d\n", i, pri);test(i, logbuf, nrecord);exit(0);} else {n++;}}}free(logbuf);free(pids);return 0;
}
import sys
import numpy as np
import matplotlib.pyplot as pltflag = sys.argv[1]
nproc = int(sys.argv[2])data = []
colors = []for fid in range(0, nproc):fname = str(fid) + '-proc.log'fd = open(fname, 'r')lines = fd.readlines()for s in lines:s = s.strip().split('\t')data.append( [int(s[0]), int(s[1]), int(s[2])] )fd.close()color = '#'for c in np.random.randint(0, 255, 3):color += format(c, '02X')colors.append(color)x_value = []
y_value = []
c_value = []if flag == 'id-time':for d in data:y_value.append(d[0])x_value.append(d[1])c_value.append(colors[d[0]])plt.scatter(x_value, y_value, c=c_value)plt.title('Data Analysis')plt.ylabel('Process No.')plt.xlabel('TIme(ms)')plt.show()if flag == 'work-time':for d in data:y_value.append(d[2])x_value.append(d[1])c_value.append(colors[d[0]])plt.scatter(x_value, y_value, c=c_value)plt.title('Data Analysis')plt.ylabel('Work Load')plt.xlabel('TIme(ms)')plt.show()

1.6.1 SCHED_OTHER

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.6.2 SCHED_RR

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.6.3 SCHED_FIFO

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

Mock.js的基本使用方法

官网网址&#xff1a;Mock.js (mockjs.com) 当前端工程师需要独立于后端并行开发时&#xff0c;后端接口还没有完成&#xff0c;那么前端怎么获取数据&#xff1f; 这时可以考虑前端搭建web server自己模拟假数据&#xff0c;这里我们选第三方库mockjs用来生成随机数据&#xf…

微信小程序开发【从0到1~入门篇】2023.08

一个小程序主体部分由三个文件组成&#xff0c;必须放在项目的根目录&#xff0c;如下&#xff1a; 文件必须作用app.js是小程序逻辑app.json是小程序公告配置app.wxss否小程序公告样式表 3. 小程序项目结构 一个小程序页面由四个文件组成&#xff0c;分别是&#xff1a; 文…

Vue2 第十九节 Vuex (一)

1.理解Vuex 2.Vuex工作原理 3.求和案例 4.Vuex的开发者工具 一.理解Vuex ① 概念&#xff1a;专门在Vue中实现集中式状态&#xff08;数据&#xff09;管理的一个Vue插件&#xff0c;对vue应用中多个组件的共享状态进行集中式的管理&#xff08;读/写&#xff09;&#xf…

JMeter(二十四)、使用吞吐量控制器实现不同的用户操纵不同的业务

一、需求 需求&#xff1a;博客系统&#xff0c;模拟用户真实行为&#xff0c;80%的用户阅读文章&#xff0c;20%的用户创建文章&#xff0c;创建文章的用户随机的删除或者修改文章。 二、脚本实现 80%的用户查看文章 20%用户创建文章 根据post_id是否能整除2&#xff0c;决…

Lua 使用 —— IO 操作

一、前言 Lua 语言是以一个脚本存在&#xff0c;所以他自身不会提供太多和外部交互的机制。需要交互则由宿主提供或是由外部库。 接下来分享下如何使用以 iso c 作为宿主&#xff0c;进行标准库的 io 操作。 二、io.input、io.output 1、io.input io.input(filename) 会以…

【windows】windows上如何使用linux命令?

前言 windows上的bat命令感觉不方便&#xff0c;想在windows上使用linux命令。 有人提供了轮子&#xff0c;本文简单介绍一些该轮子的安装与使用&#xff0c;希望能够帮助到和我有一起需求的网友。 我的答案是busybox。 1.安装busybox.exe 在这个网站上安装busybox busyb…

如何设计一个自动化测试框架

在进行自动化框架设计之前我们先来看两个问题&#xff0c;什么是自动化框架&#xff0c;设计的时候应该注意什么原则&#xff0c;然后该怎么做&#xff1f;本文会以一个web端的UI自动化测试框架设计为例 Python自动化测试&#xff1a;2023最新合集Python自动化测试开发框架【全…

fishing之第四篇使用案例一模拟登陆口

文章目录 一、访问钓鱼平台二、Sending Profiles&#xff08;发件人邮箱配置&#xff09;三、User&Groups&#xff08;接收人邮件列表&#xff09;四、Landing Pags&#xff08;钓鱼页面配置&#xff09;五、Email Templates&#xff08;邮件内容配置&#xff09;六、Campa…

【C++】二叉搜索树的模拟实现

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

AI介绍——chat gpt/文心一言/claude/bard/星火大模型/bing AI

AI体验 1. AI 介绍&#xff08;注册和使用&#xff09;1.1 Chat GPT1.2 文心一言1.3 Slack 上的 Claude1.3.1 Claude 介绍1.3.2 Claude 使用 1.4 Google的Bard1.4.1 Bard 介绍1.4.2 Bard 使用 1.5 科大讯飞的星火大模型1.5.1 星火大模型 介绍1.5.2 星火大模型 使用 1.6 new bin…

iOS Viper架构(中文版)【看懂这篇就够了】

完整源码地址 一、iOS_Viper iOS的Viper架构&#xff0c;作为一个从业多年的iOS开发者&#xff0c;我个人认为应该要会一点viper 二、前言 viper的设计模式在iOS开发中不流行&#xff0c;甚至是Swift中&#xff0c;也没有用&#xff0c;我认为比较可惜。作为iOSer,当你掌握…

2023年第四届“华数杯”数学建模思路 - 案例:随机森林

## 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是随机森林&#xff1f; 随机森林属于 集成学习 中的 Bagging&#xff08;Bootstrap AGgregation 的简称&#xff09; 方法。如果用图来表示他们之…