操作系统(第四周 第二堂)

目录

回顾

进程运行

进程的创建

 进程的工作

举例

进程的删除

举例1(走到return 0结束)

举例2(利用exit(1)结束)

进程通信 

共享内存

生产者算法

消费者算法

消息传递 

定义

 算法实现

总结


回顾

上文的重点就两个内容:一、进程调度的理解;二、队列图以及调度程序

其中进程调度的理解有:一、进程本身角度调度理解;二、计算机整体角度理解进程管理和调度

队列图共有五个队列:I/O队列、中断队列、就绪队列、时间片过期队列、创建子进程队列

调度程序:长期调度程序、短期调度程序

进程运行

研究完进程调度,现在我们来研究进程的运行,研究进程运行前要先看进程是如何创建、删除的

一个进程的一生包括:创建、工作、被调度、删除

进程的创建

所有进程(除了Pid=0的初始进程)都是由父进程创建产生

定义:创建进程称为父进程,被创建进程称为子进程

每一个进程都采用进程标识符来唯一确定进程,子进程和父进程得pid不同

进程创建必备的两个指令:fork()、exec()

fork():

一、创建子进程,子进程和父进程完全相同(虚拟地址也相同,但是物理空间实际地址不同)。完全相同也意味着父进程fork后的程序计数器为fork函数结束位置,而子进程的程序计数器也为fork函数结束位置

二、在父进程中返回子进程的pid,在子进程中返回0

三、创建子进程也意味着要在内核中新建PCB(进程控制块)

exec():

一、以新程序来取代原进程的内存空间,包括程序、栈等进程所有的成分

二、exec后子进程就有了新的虚拟地址空间,可以认为“脱离”父进程的限制

三、exec后子进程的PID保持不变

 进程的工作

进程是并行工作的,即子进程被父进程创建后和父进程一起工作(父进程利用wait(NULL)除外,该方法让父进程在子进程结束后才工作)

举例

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>// 测试创建子进程函数 pid_t fork();
int main()
{pid_t pid = fork();if(-1 == pid){//创建子进程失败return -1;}if(0 == pid){//子进程printf("I am child, my fork:%d\n", pid);printf("I am child, my pid:%d, ppid:%d\n",getpid(),getppid());sleep(5);printf("I am child, I have finished\n");  }else{//父进程 printf("I am father, my fork:%d\n", pid);      printf("I am father, my pid:%d, ppid:%d\n",getpid(),getppid());sleep(5);printf("I am father, I have finished\n");   }return 0;
}

执行结果为:

程序运行的关键点: 

1、父进程先运行:由于子进程由fork函数创建,所以需要耗费一些时间。

2、父子进程并行运行:父进程利用sleep函数休息时,可以看到子进程也输出了其值,说明父子进程目前共同在运行

3、fork返回值:父进程的fork返回值为子进程的pid,子进程的fork返回值为0

4、pid是进程标识符:子进程和父进程的pid的值不同

进程的删除

进程的删除主要有两种:

1、进程走到return 0 自己结束 

2、进程调用exit(1)结束

举例1(走到return 0结束)

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>// 测试创建子进程函数 pid_t fork();
int main()
{pid_t pid = fork();if(-1 == pid){//创建子进程失败return -1;}if(0 == pid){//子进程printf("I am child, my fork:%d\n", pid);printf("I am child, my pid:%d, ppid:%d\n",getpid(),getppid());sleep(5);printf("I am child, I have finished\n");  }else{//父进程 wait(NULL) printf("I am father, my fork:%d\n", pid);      printf("I am father, my pid:%d, ppid:%d\n",getpid(),getppid());sleep(5);printf("I am father, I have finished\n");   }printf("%d 号进程已结束\n",pid);return 0;
}

 结果为:

关键点:在父进程中调用wait(NULL)函数让父进程在子进程结束后才开始运行 

举例2(利用exit(1)结束)

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>// 测试创建子进程函数 pid_t fork();
int main()
{pid_t pid = fork();if(-1 == pid){//创建子进程失败return -1;}if(0 == pid){//子进程printf("I am child, my fork:%d\n", pid);printf("I am child, my pid:%d, ppid:%d\n",getpid(),getppid());sleep(5);printf("I am child, I have finished\n");exit(1);  }else{//父进程 wait(NULL) printf("I am father, my fork:%d\n", pid);      printf("I am father, my pid:%d, ppid:%d\n",getpid(),getppid());sleep(5);printf("I am father, I have finished\n");   }printf("%d 号进程已结束\n",pid);return 0;
}

执行结果为:

关键点:子进程运行到exit函数后就自己删除自己,父进程开始运行 

进程通信 

操作系统内并发执行的进程可以是独立的也可以是协作的,协作完成的进程就涉及到进程间通信

进程通信主要有两种方式:1、共享内存  2、消息传递

图中关键点: 

1、共享内存没有内核参与,消息传递需要内核参与

2、共享内存速度快于消息传递,但是共享内存要避免内存冲突。在多处理器系统上,共享内存有高速缓存一致性的问题

共享内存

共享内存实现通信一定要面临一种情况:其中一个进程是消息的发送者,另一个进程是消息的接收者。

这样我们必须要设计算法保证:消息接受者知道消息发送者何时发送

生产者算法
while(true){while(((in+1)%BUFFER_SIZE)==out); //共享内存满了,就不能生产等待消费者进程拿buffer[in]=next_produced;in=(in+1))%BUFFER_SIZE
}
消费者算法
item next_consumed;
while(true){while(in==out);//此时共享内存是空的,无法拿东西next_comsumed=buffer[out];out=(out+1)%BUFFER_SIZE;

算法关键点: 

1、缓冲区最大值为BUFFER_SIZE-1(人为设定)

2、in+1==out设定为满,in==out设定为空

3、如果想要缓冲区最大值为BUFFER_SIZE,需要另设一个标志数用来记录缓冲区是满的还是空的。否则满的和空的都是in==out成立则无法区分

4、本质就是双指针实现,如上图所示

消息传递 

定义

关键点:

1、消息传递对于分布式环境(硬件不同)的两个进程的通信特别有用

2、消息传递必须通过系统调用完成,所以必须陷入内核

3、消息传递一共有两种通信方式,第一种是直接通信方式,第二种是间接通信方式

首先要知道一个消息是由消息头和消息体组成的,消息头里包括:发送进程ID、接收进程ID、消息类型、消息长度等格式化的信息(计算机网络中发送的“报文”其实就是一种格式化的消息)。

直接通信方式,如下:

发送进程把它想要发送的消息,通过发送原语发送给接收进程,然后这些消息会被放到接收进程的消息队列里面,接着接收进程通过接收原语一个个读取消息队列中的消息,这样发送进程和接收进程就实现了线程通信。

间接通信方式,如下:

对于间接通信方式,进程1会先通过发送原语把消息放到一个信箱中,然后进程2会通过接收原语从信箱中读取这些消息。

 算法实现

总结

本文到这里就结束啦~~这堂课的内容较为杂乱、复杂,但是学一学拓展一下知识是非常好的呀~~
如果觉得对你有帮助,辛苦友友点个赞哦~

知识来源:操作系统概念(黑宝书)、山东大学高晓程老师PPT及课上讲解。不要私下外传

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

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

相关文章

Redis:发布和订阅

文章目录 一、介绍二、发布订阅命令 一、介绍 Redis的发布和订阅功能是一种消息通信模式&#xff0c;发送者&#xff08;pub&#xff09;发送消息&#xff0c;订阅者&#xff08;sub&#xff09;接收消息。这种功能使得消息发送者和接收者不需要直接建立连接&#xff0c;而是通…

《前端防坑》- JS基础 - 你觉得typeof nullValue === null 么?

问题 JS原始类型有6种Undefined, Null, Number, String, Boolean, Symbol共6种。 在对原始类型使用typeof进行判断时, typeof stringValue string typeof numberValue number 如果一个变量(nullValue)的值为null&#xff0c;那么typeof nullValue "?" const u …

商标没有去注册有哪些不好的影响!

有些商家咨询普推知产老杨&#xff0c;商标没有去注册有哪些不好的影响&#xff0c;其实对企业来说还有许多实际不利的影响&#xff0c;有时代价比注册一个商标要大很多。 想的商标名称没去注册商标&#xff0c;如果别人抢注拿下商标注册证&#xff0c;那就会涉及侵权&#xf…

树上启发式合并(dsu on tree)学习

声明&#xff1a;本文部分内容摘自OI Wiki网站。详情可自行查看学习。 洛谷 P9233 题目实际上是蓝桥杯 2023 年 A 组省赛的一道题。题干大致的意思是&#xff0c;给定一个含有 n n n 个结点&#xff0c;并且以 1 1 1 为根的一棵树&#xff0c;每个节点 i i i 都有一个颜色 …

springcloud第4季 springcloud-alibaba之nacos篇

一 nacos 1.1 nacos作用介绍 nacos是一个分布式的配置中心和注册发现中心。 nacos是 dynamic naming configuration service nacosconfigbus 实现动态刷新&#xff1b;nacosconsul 1.2 各个注册中心对比 注册中心CAP模型控制台管理社区活跃度EureakaAp支持低zkcp不支持中…

将Visio绘图导出PDF文件,使其自适应大小,并去掉导入Latex的边框显示

问题描述 将Visio绘图导成pdf文件&#xff0c;首先在Visio绘图如下&#xff1a; 如果直接导出或者另存为pdf文件&#xff0c;则会发现pdf文件是整个页面大小&#xff0c;而不是图片大小。而且在导入latex等排版工具现实时&#xff0c;会显示边框。 问题解决 1.调整Visio中的页…

【攻防世界】题目名称-文件包含

看到 include()&#xff0c;想到文件包含&#xff0c;用php伪协议。 知识点 看到 include()&#xff0c;require()&#xff0c;include_once()&#xff0c;require_once() &#xff0c;想到文件包含&#xff0c;用php伪协议 ?filenamephp://filter/readconvert.base64-encode/…

zabbix监控配置(添加主机、主机组和添加监控项等)

zabbix监控配置 文章目录 zabbix监控配置1.添加主机组2.添加主机&#xff08;linux&#xff09;3.添加主机&#xff08;windows&#xff09;4.监控项配置&#xff08;通过模板添加&#xff09;5.监控项配置&#xff08;手动添加&#xff09; 1.添加主机组 2.添加主机&#xff0…

【C语言】字符串函数和内存函数及其模拟实现

文章目录 前言 一、常见字符串库函数1.strlen函数2.长度不受限制的字符串函数2.1 strcpy2.2 strcat2.3 strcmp 3.长度受限制的字符串函数3.1 strncpy3.2 strncat3.3 strncmp 二、字符串查找函数strstrstrtok 三、strerror函数四、内存操作函数1.memcpy2.memmove3.memcmp 五、字…

水经微图IOS版5.2.0发布

随时随地&#xff0c;微图一下&#xff01; 水经微图&#xff08;简称“微图”&#xff09;IOS新版已上线。 在该版本中主要新增图层树节点排序功能、常规&#xff08;矩形、圆、椭圆、扇形&#xff09;绘制功能、地形夸张等主要功能。 当前版本 当前版本号为&#xff1a;5…

蓝桥杯第2152题——红绿灯

问题描述 爱丽丝要开车去上班, 上班的路上有许多红绿灯, 这让爱丽丝很难过。为 了上班不迟到, 她给自己的车安装了氮气喷射装置。现在她想知道自己上班最 短需要多少时间。 爱丽丝的车最高速度是 米每秒, 并且经过改装后, 可以瞬间加速到小于 等于最高速的任意速度, 也可以瞵…

js可视化爬取数据生成当前热点词汇图

功能 可以爬取到很多数据&#xff0c;并且生成当前的热点词汇图&#xff0c;词越大越热门&#xff08;词云图&#xff09; 这里以b站某个评论区的数据为例&#xff0c;爬取63448条数据生成这样的图片 让我们能够更加直观的看到当前的热点 git地址 可以直接使用&#xff0c;中文…

【C++】类和对象②(类的默认成员函数:构造函数 | 析构函数)

&#x1f525;个人主页&#xff1a;Forcible Bug Maker &#x1f525;专栏&#xff1a;C 目录 前言 类的6个默认成员函数 构造函数 概念 构造函数的特性及用法 析构函数 概念 析构函数的特性及用法 结语 前言 本篇主要内容&#xff1a;类的6个默认成员函数中的构造函…

mysql四种引擎区别

MySQL 提供了多种不同的数据库引擎&#xff0c;其中最常见的有 MyISAM、InnoDB、MEMORY 和 BLACKHOLE。这四个引擎分别有以下特点&#xff1a; 1. MyISAM MyISAM 是 MySQL 的默认引擎。它对于只有较少的修改、大量读取的应用场景具有良好的性能。它不支持事务处理&#xff0c;也…

算法第四十一天-排除排序链表中的重复元素Ⅱ

排除排序链表中的重复元素Ⅱ 题目要求 解题思路 题意&#xff1a;在一个有序链表中&#xff0c;如果一个节点的值出现不止一次&#xff0c;那么把这个节点删除掉 重点&#xff1a;有序链表&#xff0c;所以&#xff0c;一个节点的值出现不止一次&#xff0c;那么他们必相邻。…

LeetCode-416. 分割等和子集【数组 动态规划】

LeetCode-416. 分割等和子集【数组 动态规划】 题目描述&#xff1a;解题思路一&#xff1a;01背包问题&#xff0c;动规五部曲解题思路二&#xff1a;0解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分…

【UE 委托】如何利用函数指针理解委托的基本原理

目录 0 引言1 函数指针模拟多播委托 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;UE虚幻引擎专栏&#x1f4a5; 标题&#xff1a;【UE 委托】如何利用函数指针理解委托的基本原理❣️ 寄语&#xff1a;书到用时方恨少&#xff0c;事非经过不知难…

OpenCV C++学习笔记

1.图像的读取与显示 1.1 加载并显示一张图片 #include<opencv2/opencv.hpp> #include<iostream>using namespace cv; using namespace std; int main(int argc,char** argv){Mat srcimread("sonar.jpg");//读取图像if(src.empty()){printf("Could…

ORA-00600: internal error code, arguments: [krbcbp_9]

解决方案 1、清理过期 2、control_file_record_keep_time 修改 恢复时间窗口 RMAN (Recovery Manager) 是 Oracle 数据库的备份和恢复工具。在 RMAN 中&#xff0c;可以使用“恢复窗口”的概念来指定数据库可以恢复到的时间点。这个时间点是基于最近的完整备份或增量备份。 …

创建一个qt登录界面,密码账号正确转到窗口2,否则弹出对话框提示账号密码错误,窗口2有四个按键,三个按键可以朗读按键文本,第四个退出。

作业要求&#xff1a; 主函数&#xff1a; int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();Form1 f;//连接窗口1的信号函数和窗口2打开的lambda函数Widget::connect(&w,&Widget::login,[&](){f.show();});return a.exec(); }窗…