操作系统:进程1

news2024/11/18 16:30:01

一.进程

1.什么是进程

一个进程创建,他会生成几块:

  • 代码段:进程执行的程序代码
  • 数据段:全局变量,静态变量,在进程生命周期中是动态可变的
  • 堆:动态分配的内存区域,malloc、calloc、realloc等函数进行开辟
  • 栈:用于存储局部变量、函数参数和返回地址
  • PCB进程控制块:包含进程ID(PID),进程状态,程序计数器(吓一条指令的位置),进程优先级等等

进程是资源分配和调度的基本单位

进程是资源分配的最小单位

线程是最小的调度单位

2.进程中的三态模型

  • 阻塞态:这个进程需要相应的资源,而现在需要等待相应的资源,那么这个进程就进入到阻塞态,CPU会将这个进程给拿下CPU,去执行就绪在就绪队列中的第一个进程。
  • 就绪态:一个进程需要运行,并且他所有的需求都满足了,就等待CPU去执行,那么这个进程会在这个就绪队列中进行排队,等待CPU的调度执行
  • 运行态:这个进程在CPU上执行

挂起

  • 挂起:在挂起这个进程时,会将这些运行在内存上的内容给写入到磁盘中或交换区中,然后释放内存,在记录上下文(记录上下文的作用就是,为了让你回到在你挂起这个进程前那个状态,和玩游戏存档的意思差不多)
  • 唤醒:将刚刚写入到磁盘的内容,又写入到内存中,到达就绪态,等待操作系统的调度

进程详细的五态

对于3态模型,只多了创建态和终止态。

3.进程的控制 

如何实现的原子性?

在原语时,执行关中断指令,将中断关闭掉,这样CPU就不会中断这个原语的执行,在执行完成原语后,执行开中断指令,将中断打开。这样就实现了原语的原子性,在执行原语的过程中就不会被中断。

4.调度的基本概念

        为什么需要了解如何进行调度?

        当有一堆任务需要处理,但由于资源有限,这些事情没有同时处理。这就需要确定某种规则来决定处理这些任务的顺序,这就是”调度“研究”的问题

        能否进行调度切换进程的情况:

        进行切换是有代价的,如果过度频繁进行调度、切换,会使系统的效率降低。

 调度算法:

1.时间片轮转算法

        给每个进入到就绪队列中的进程分配一个时间片,这个时间片的大小需要写程序的我们来决定,不能太短,也不能太长。然后每个程序在CPU上执行的时间就是时间片的大小,如果执行完成可以先退出然后让出CPU,如果没有在时间片规定的时间完成,那么也要让出CPU让就绪队列中下一个进程进行执行,然后让出CPU后又到就绪队列中进行排队,等待下一次的CPU调度执行。

2.优先级调度算法

 优先级调度算法分为:

  • 静态:进程在创建时就确定了优先级,这个进程在生命周期中优先级不会改变
  • 动态:在创建时确定了一个优先级,在生命周期的过程中,操作系统会通过规定进行对应的优先级改变
3.多级反馈队列调度算法

  • 特点:进程可以在不同优先级队列之间移动。新进程进入高优先级队列,如果未能在规定时间完成则降级。
  • 优点:兼顾响应时间和吞吐量,适应性强。
  • 缺点:配置参数(如队列数量、时间片等)复杂。
4.短作业优先
  • 特点:优先调度运行时间最短的进程。
  • 优点:可以最小化平均等待时间。
  • 缺点:难以准确预测每个进程的运行时间;可能导致长作业得不到及时处理(即“饥饿”)。
5.最短剩余时间优先
  • 特点:是SJF的抢占式版本。每次调度时选择剩余执行时间最短的进程。
  • 优点:可以进一步减少平均等待时间。
  • 缺点:和SJF一样,难以预测执行时间,并且会导致频繁的上下文切换。

  对比短作业优先就是,假如P1进程需要执行时间是10s,P2执行时间是20S,现在执行P1已近5s了,来了一个新进程P3执行是减是3S,那么CPU会将P1给拿下放入到就绪队列中,来执行P3。短作业优先就是P1执行完成了才执行P3

6.先来先服务
  • 特点:按进程到达就绪队列的顺序进行调度,先到达的进程先调度。
  • 优点:简单易实现。
  • 缺点:可能导致“等待时间长”的问题(即“队头阻塞”)。

5.进程拷贝

        进程拷贝时,他们会共享物理内存页面,但是这些内存页面现在是只读的。

        其中一个进程需要堆这个内存页面进行写入时,那么就会创建该内存页的副本,然后给该进程附上可写的权限。

        这样可以节省系统资源,防止创建一个子进程就立刻复制整个地址空间,减少不必要的空间。        

6.创建进程

fork函数
#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);

fork函数创建子进程的关键点:

  • 共享资源:子进程继承了父进程的大部分资源,包括打开的文件描述符、环境变量、优先级、控制终端等。
  • 独立地址空间:虽然子进程最初共享父进程的地址空间,但它们有独立的地址空间,修改内存不会影响对方。
  • 执行路径fork() 返回值用于区分父子进程。子进程返回 0,父进程返回子进程的 PID。
  • 进程调度:子进程和父进程是并行执行的,具体谁先执行由操作系统调度决定。

例子:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>


int main() {

    int n;
    //创建子进程
    pid_t child_pid = fork();

    if (child_pid < 0) {
        perror("fork");
        exit(1);
    }

    //当child_pid为04时说明是子进程
    if (child_pid == 0) {
        n = 6;
        while (n > 0) {
            printf("child self = %d, parent = %d\n", getpid(), getppid());
            n--;
        }
    } 
    //不为0说明是父进程
    else {
        n = 3;
        while (n > 0) {
            printf("parent self = %d, parent = %d\n", getpid(), getppid());
            n--;
        }
    }
    
    return 0;
}

       你会发现每次输出的结果都是不一样的。

 孤儿进程 

        那么像这种情况就是父进程先执行完成了,子进程还在执行,但是没有父进程为子进程收尸(回收资源),那么这个子进程就叫做孤儿进程,那么谁会为他收尸呢,也就是我们系统最初的那个进程0号进程。也叫做init进程(或者现代系统的systemd)接管,我们也可以称它为孤儿院。

僵尸进程

        当一个进程终止后,其父进程还没有读取它的退出状态,这个进程就被称为僵尸进程。

        如何处理我们调用wait()或者waitpid()来读取子进程的状态,来等待子进程的退出状态,这样就可以为子进程进行收尸。

wait和waitpid()
pid_t wait(int *status);

pid_t waitpid(pid_t pid, int *status, int options);

wait:

  • 功能wait 阻塞调用进程,直到其某个子进程终止。如果一个子进程已经终止,那么 wait 会立即返回。
  • 参数status 是一个指向整数的指针,用于存储子进程的退出状态。如果 statusNULL,则退出状态会被丢弃。
  • 返回值:返回终止的子进程的进程 ID。如果调用出错(例如,没有子进程),则返回 -1 并设置 errno

waitpid:

  • 功能waitpid 提供了比 wait 更细粒度的控制,允许父进程等待特定的子进程终止,或者以非阻塞方式等待。
  • 参数
    • pid:指定要等待的子进程 ID。如果 pid 为 -1,则等待任何子进程(等同于 wait)。
    • status:同 wait,用于存储子进程的退出状态。
    • options:提供额外的选项控制,如 WNOHANG(非阻塞方式)和 WUNTRACED(也会返回已停止的子进程)。
  • 返回值:成功时返回子进程的 PID,失败时返回 -1 并设置 errno

        如何获取退出状态,可以在Linux系统中的man手册查看。

接着上面那个例子来进行优化:
 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <wait.h>


int main() {

    int n;
    int state;
    //创建子进程
    //在子进程中child_pid 为0
    //父进程为fork的返回值
    pid_t child_pid = fork();

    if (child_pid < 0) {
        perror("fork");
        exit(1);
    }

    //当child_pid为04时说明是子进程
    if (child_pid == 0) {
        n = 6;
        while (n > 0) {
            printf("child self = %d, parent = %d\n", getpid(), getppid());
            n--;
        }
    } 
    //不为0说明是父进程
    else {
        n = 3;
        while (n > 0) {
            printf("parent self = %d, parent = %d\n", getpid(), getppid());
            n--;
        }
        int ret = wait(&state);
        if (ret < 0) {
            perror("wait error");
            exit(1);
        }
        //看通过stata判断子进程是否正常退出
        if (WIFEXITED(state)) {
            //正常退出输出子进程PID和退出状态
            printf("child process %d is sucess exit %d\n", child_pid, WEXITSTATUS(state));
        } else {
            //不正常输出子进程PID
            printf("child process %d is not sucess exit\n", child_pid);
        }
    }
    
    return 0;
}

 

 

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

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

相关文章

Ubuntu安装mysql,并使用IDEA连接mysql

一、安装Mysql 1.更新源 sudo apt-get update2.安装Mysql apt-get install mysql-server3.检查是否安装成功 mysql --version4.启动和关闭mysql的命令如下: #启动 sudo service mysql start #关闭 sudo service mysql stop #重启 sudo service mysql restart5.查看mysql运行…

JavaDS —— 二叉搜索树、哈希表、Map 与 Set

前言 我们将学习 Map 与 Set 这两个接口下的 TreeMap 与 TreeSet &#xff0c;HashMap 与 HashSet &#xff0c;在学习这四个类使用之前&#xff0c;我们需要先学习 二叉搜索树与 哈希表的知识。 二叉搜索树 在学习二叉树的时候&#xff0c;我们就已经了解过二叉搜索树的概念…

ctfshow-web入门-php特性(web142-web146)

目录 1、web142 2、web143 3、web144 4、web145 5、web146 1、web142 要求 v1 是数字&#xff0c;之后将 v1乘以 0x36d&#xff08;即16进制的869&#xff09;五次&#xff0c;然后将结果转换为整数并赋值给变量 $d&#xff0c;使用 sleep 函数使程序休眠 $d 秒&#xff0c…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 项目排期安排(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题目在线…

CentOS7 yum报错Cannot find a valid baseurl for repo

问题 Loaded plugins: fastestmirror Determining fastest mirrors Could not retrieve mirrorlist http://mirrorlist.centos.org/?release7&archx86_64&repoos&infravag error was 14: curl#6 - "Could not resolve host: mirrorlist.centos.org; Unknown…

基于多种机器学习算法的短信垃圾分类模型

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主导入第三方库读取数据数据预处理数据分析与可视化机器学习建模贝叶斯逻辑回归支持向量机随机森林XGBoost总结每文一语 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私…

阅读笔记2:董超底层视觉之美|底层视觉是什么?

原文链接&#xff1a;https://mp.weixin.qq.com/s/9EQNwXqCM6odwe5n9dOrmw 本文针对底层视觉给出了一个大致的定义&#xff0c;然后通过底层视觉与人工智能、计算机视觉、图像处理等相关概念的对比来对底层视觉做了进一步的界定。 1. 底层视觉是什么 以像素级图像为输入、处…

利用小爱同学与点灯科技+esp8266+舵机,制作智能关灯神器:小白也可制作,米家同步设备可实现多部手机进行控制。(亲测有用)

利用小爱同学与点灯科技&#xff0c;制作智能关灯神器&#xff1a;小白也可制作&#xff0c;米家同步设备可实现多部手机进行控制。 文章目录 利用小爱同学与点灯科技&#xff0c;制作智能关灯神器&#xff1a;小白也可制作&#xff0c;米家同步设备可实现多部手机进行控制。1.…

vue3 快速入门 (六) : vue中调用HTTP请求

1. 本文环境 Vue版本 : 3.4.29Node.js版本 : v20.15.0系统 : Windows11 64位IDE : VsCode 1.91.0 2. 访问HTTP 在Vue中&#xff0c;访问HTTP&#xff0c;可以使用axios第三方库。 axios 是一个基于 promise 的网络请求库&#xff0c;可以用于浏览器和 node.js。 axios使用简…

一步步理清开源路径规划导航引擎GraphHopper

一步步理清开源路径规划导航引擎GraphHopper&#xff0c;学习应用 GraphHopper简介 源码用 Java 编写&#xff0c;开发人员可以通过 Maven 轻松上手。可以用作** Java 库**来计算两个或多个点之间路线的距离、时间、逐向指示和许多道路属性。可以用作独立的 Web 服务器来计算…

redis的学习

! 快速入门 安装 1.使用docker安装redis docker pull redisdocker run -d --name redis -p 6379:6379 --restart unless-stopped -v /etc/docker/Redis/data:/data -v /etc/docker/Redis/conf/redis.conf:/usr/local/etc/redis/redis.conf redis redis-server /usr/local/e…

Python 百题(实战快速掌握语法)_2(链表)

目录 实现链表类 挑战介绍 挑战内容 挑战要求 示例代码 版权说明 参考答案 代码分析&#xff1a; Node 类 LinkedList 类 方法分析 总结 删除链表的重复项 挑战介绍 挑战内容 挑战要求 示例代码 版权说明 参考答案 代码分析&#xff1a; 寻找链表倒数第 k…

算法笔记--知识点记录2

enumerate函数 enumerate 是 Python 中的一个内置函数&#xff0c;它用于将一个可遍历的数据对象&#xff08;如列表、元组或字符串&#xff09;组合为一个索引序列&#xff0c;同时列出数据和数据下标&#xff0c;通常用在 for 循环当中。 使用 enumerate 可以同时获得每个元…

什么是C++活锁?

听过太多的死锁&#xff08;Deadlock&#xff09;&#xff0c;今天来聊聊什么是C活锁&#xff08;Livelock&#xff09;。 C中的活锁&#xff08;Livelock&#xff09;并非特指C语言本身的一个概念&#xff0c;而是并发编程和操作系统中可能遇到的一种现象。活锁指的是任务或者…

数据库 执行sql添加删除字段

添加字段&#xff1a; ALTER TABLE 表明 ADD COLUMN 字段名 类型 DEFAULT NULL COMMENT 注释 AFTER 哪个字段后面; 效果&#xff1a; 删除字段&#xff1a; ALTER TABLE 表明 DROP COLUMN 字段;

【C++】C++入门知识(上)

好久不见&#xff0c;本篇介绍一些C的基础&#xff0c;没有特别的主题&#xff0c;话不多说&#xff0c;直接开始。 1.C的第一个程序 C中需要把定义文件代码后缀改为 .cpp 我们在 test.cpp 中来看下面程序 #include <stdio.h> int main() {printf("hello world\n…

Linux文件与相关函数的知识点3

main函数参数 int main(int argc,char *argv[]) { return 0; } C语言规定了main函数的参数只能有两个&#xff0c;一个是argc,一个是argv并且&#xff0c;argc只能是整数&#xff0c;第二个必须是指向字符 串的指针数组。 argc: 参数表示命令行中参数的个数&#xff0…

【建议收藏】CTF网络安全夺旗赛刷题指南(非常详细)零基础入门到精通,收藏这一篇就够了

在数字化浪潮汹涌澎湃的今天&#xff0c;网络安全已成为国家、企业和个人无法忽视的重要议题。为了挖掘和培养网络安全人才&#xff0c;一场场紧张刺激、充满智慧的CTF&#xff08;Capture The Flag&#xff09;安全竞赛应运而生。 一、CTF安全竞赛简介 CTF安全竞赛&#xff0c…

鸿蒙仓颉语言之【安全密码库crypto4cj】功能示例

功能示例 MD5使用样例 from crypto4cj import md5cj.*main() { var md: Array<UInt8> Array<UInt8>(16, item: 0)var result: String String(Array<Char>(33, item: 0))var str: String "helloworld"var ret md5(str.toUtf8Array(), md)r…

lua 游戏架构 之 游戏 AI (六)ai_auto_skill

定义一个为ai_auto_skill的类&#xff0c;继承自ai_base类。ai_auto_skill类的目的是在AI自动战斗模式下&#xff0c;根据配置和条件自动选择并使用技能。 lua 游戏架构 之 游戏 AI &#xff08;一&#xff09;ai_base-CSDN博客文章浏览阅读379次。定义了一套接口和属性&#…