Linux C 进程编程

news2024/11/20 11:40:04

进程编程

  • 进程介绍
    • 进程的定义
    • 进程和线程以及程序的区别
    • 进程块PCB
      • 进程的状态
      • 相关指令
    • 进程调度算法
      • 先来先服务调度算法 FCFS
      • 短作业(进程)优先调度算法 SJF
      • 优先权调度算法 FPF
        • 优先权调度算法的类型
          • 非抢占式优先权算法
          • 抢占式优先权算法
        • 优先权类型
          • 静态优先权
          • 动态优先权
        • 高响应比优先调度算法
      • 基于时间片的轮转调度算法
    • 进程的状态
    • 相关函数
      • fork  创建子进程
      • vfork  创建子进程
      • system  Shell命令创建子进程
      • execl  创建子进程
      • 四个创建子进程函数的区别
      • 进程的退出
    • 进程退出产生的相关问题
      • 孤儿进程
      • 僵尸进程
      • 下面提供了一些解决措施
  • 参考文献

进程介绍

进程的定义

  官方的来说,进程是程序在某个数据集合上的一次运行活动,也是操作系统进行资源分配和保护的基本单位。
  通俗的讲,进程就是在程序编译之后,运行起来的二进制文件。

进程和线程以及程序的区别

  程序是存储在磁盘上的可执行文件,是一组指令的集合,它是静态的,而进程包含了程序的代码和程序运行时所需的资源,如内存、文件描述符等。每个进程都是独立的,有自己的地址空间和资源,进程之间是相互独立的。线程则是进程中的执行单元,一个进程可以包含多个线程,这些线程共享进程的资源,包括内存和文件描述符。线程之间可以共享数据,并且可以更高效地进行通信和同步。
  因此,进程和线程都是程序的执行实例,它们之间的区别在于资源的独立性和共享性。程序是静态的代码和数据的集合,只有在运行时才会成为进程或线程。

进程块PCB

  进程控制块 (PCB)是系统为了管理进程设置的一个专门的数据结构。 系统用它来记录进程的外部特征,描述进程的运动变化过程。 同时,系统可以利用PCB来控制和管理进程,所以说,PCB(进程控制块)是系统感知进程存在的唯一标志。
  Linux中可以使用 “ps auxjf” 指令查看进程的静态信息,使用 “top” 指令查看进程的动态信息。

字母解释
a现在一个终端的所有进程
u显示进程的归属用户以及内存使用情况
x显示出和终端没有关联的进程
j显示进程归属的进程组id,会话id,父进程id
f以ascii形式显示出进程的层次关系

进程的状态

在这里插入图片描述

状态状态属性
R:执行状态<:优先级高的进程,比优先级的进程运行的次数更频繁。
S:休眠状态N:低优先级的进程
Z:僵尸进程s:包含子进程
T:停止状态I:位于后台的进程组
D:无法中断的休眠状态+:进程组内的前台进程

相关指令

1) 进程运行切换
  ① 在终端后台运行一个进程:./ 可执行命令 空格 &
  ② 查看终端的后台进程:jobs
  ③ 让进程n到后台去:bg %n
  ④ 让后台运行的进程n到前台来:fg %n
  ⑤ 把前台进程已停止状态进入后台进程:ctrl + z。
  注:一个终端只能有一个前台进程,剩余的所有进程都是后台进程。
2) 杀死进程:kill 空格 参数 空格 杀死的目标(进程 ID),常用参数为-9。

进程调度算法

  这里只做简单介绍,具体和算法部分可以自行单独搜索。

先来先服务调度算法 FCFS

  先来先服务(FCFS)调度算法是一种最简单的调度算法,该算法既可用于作业调度,也可用于进程调度。当在作业调度中采用该算法时,每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存,为它们分配资源、创建进程,然后放入就绪队列。在进程调度中采用 FCFS 算法时,则每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。
  FCFS 算法比较有利于长作业(进程),而不利于短作业(进程)。

短作业(进程)优先调度算法 SJF

  短作业(进程)优先调度算法 SJ§F,是指对短作业或短进程优先调度的算法。它们可以分别用于作业调度和进程调度。短作业优先(SJF)的调度算法是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行。而短进程优先(SPF)调度算法则是从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再重新调度。
  SJF 调度算法能有效地降低作业的平均等待时间,提高系统吞吐量。但是该算法对长作业不利,并且不能保证紧迫性作业(进程)会被及时处理。

优先权调度算法 FPF

优先权调度算法的类型

  为了照顾紧迫型作业,使之在进入系统后便获得优先处理,引入了最高优先权优先(FPF)调度算法。此算法常被用于批处理系统中,作为作业调度算法,也作为多种操作系统中的进程调度算法,还可用于实时系统中。当把该算法用于作业调度时,系统将从后备队列中选择若干个优先权最高的作业装入内存。当用于进程调度时,该算法是把处理机分配给就绪队列中优先权最高的进程,这时,又可进一步把该算法分成如下两种。

非抢占式优先权算法

  在这种方式下,系统一旦把处理机分配给就绪队列中优先权最高的进程后,该进程便一直执行下去,直至完成;或因发生某事件使该进程放弃处理机时,系统方可再将处理机重新分配给另一优先权最高的进程。
  这种调度算法主要用于批处理系统中;也可用于某些对实时性要求不严的实时系统中。

抢占式优先权算法

  在这种方式下,系统同样是把处理机分配给优先权最高的进程,使之执行。但在其执行期间,只要又出现了另一个其优先权更高的进程,进程调度程序就立即停止当前进程(原优先权最高的进程)的执行,重新将处理机分配给新到的优先权最高的进程。因此,在采用这种调度算法时,是每当系统中出现一个新的就绪进程 i 时,就将其优先权 Pi 与正在执行的进程 j 的优先权 Pj 进行比较。如果 Pi≤Pj,原进程 Pj 便继续执行;但如果是 Pi>Pj,则立即停止 Pj 的执行,做进程切换,使 i 进程投入执行。
  显然,这种抢占式的优先权调度算法能更好地满足紧迫作业的要求,故而常用于要求比较严格的实时系统中,以及对性能要求较高的批处理和分时系统中。

优先权类型

  对于最高优先权优先调度算法,其关键在于:它是使用静态优先权,还是用动态优先权,以及如何确定进程的优先权。

静态优先权

  静态优先权是在创建进程时确定的,且在进程的整个运行期间保持不变。一般地,优先权是利用某一范围内的一个整数来表示的,例如,0~7 或 0~255 中的某一整数,又把该整数称为优先数,只是具体用法各异:有的系统用“0”表示最高优先权,当数值愈大时,其优先权愈低;而有的系统恰恰相反。
  确定进程优先权的依据有如下三个方面:进程类型、进程对资源的需求、用户要求。

动态优先权

  动态优先权是指在创建进程时所赋予的优先权,是可以随进程的推进或随其等待时间的增加而改变的,以便获得更好的调度性能。例如,我们可以规定,在就绪队列中的进程,随其等待时间的增长,其优先权以速率 a 提高。若所有的进程都具有相同的优先权初值,则显然是最先进入就绪队列的进程将因其动态优先权变得最高而优先获得处理机,此即FCFS 算法。若所有的就绪进程具有各不相同的优先权初值,那么,对于优先权初值低的进程,在等待了足够的时间后,其优先权便可能升为最高,从而可以获得处理机。当采用抢占式优先权调度算法时,如果再规定当前进程的优先权以速率 b 下降,则可防止一个长作业长期地垄断处理机。

高响应比优先调度算法

  在批处理系统中,短作业优先算法是一种比较好的算法,其主要的不足之处是长作业的运行得不到保证。如果我们能为每个作业引入前面所述的动态优先权,并使作业的优先级随着等待时间的增加而以速率 a 提高,则长作业在等待一定的时间后,必然有机会分配到处理机。该优先权的变化规律可描述为:

优先权 =  等待时间  +  要求服务时间   要求服务时间  =\frac{\text { 等待时间 }+ \text { 要求服务时间 }}{\text { 要求服务时间 }} = 要求服务时间  等待时间 + 要求服务时间 

  由于等待时间与服务时间之和就是系统对该作业的响应时间,故该优先权又相当于响应比 RP。据此,又可表示为:

R P =  等待时间  +  要求服务时间   要求服务时间  =  响应时间   要求服务时间  R_{\mathrm{P}}=\frac{\text { 等待时间 }+ \text { 要求服务时间 }}{\text { 要求服务时间 }}=\frac{\text { 响应时间 }}{\text { 要求服务时间 }} RP= 要求服务时间  等待时间 + 要求服务时间 = 要求服务时间  响应时间 

基于时间片的轮转调度算法

  如前所述,在分时系统中,为保证能及时响应用户的请求,必须采用基于时间片的轮转式进程调度算法。在早期,分时系统中采用的是简单的时间片轮转法;进入 20 世纪 90年代后,广泛采用多级反馈队列调度算法。

进程的状态

1 ) 就绪(Ready)状态
  当进程已分配到除 CPU 以外的所有必要资源后,只要再获得 CPU,便可立即执行,进程这时的状态称为就绪状态。在一个系统中处于就绪状态的进程可能有多个,通常将它们排成一个队列,称为就绪队列。
2 ) 执行状态
  进程已获得 CPU,其程序正在执行。在单处理机系统中,只有一个进程处于执行状态;在多处理机系统中,则有多个进程处于执行状态。
3 ) 阻塞状态
  正在执行的进程由于发生某事件而暂时无法继续执行时,便放弃处理机而处于暂停状态,亦即进程的执行受到阻塞,把这种暂停状态称为阻塞状态,有时也称为等待状态或封锁状态。致使进程阻塞的典型事件有:请求 I/O,申请缓冲空间等。通常将这种处于阻塞状态的进程也排成一个队列。有的系统则根据阻塞原因的不同而把处于阻塞状态的进程排成多个队列。

在这里插入图片描述

相关函数

fork  创建子进程

头文件:
   #include<unistd.h>
函数原型::pid_t fork(void);
函数介绍:fork()会产生一个新的子进程,其子进程会复制父进程的数据与堆栈空间,并继承父进程的用户代码,组代码,环境变量、已打开的文件代码、工作目录和资源限制等。父子之间抢占CPU执行。
返回值:如果 fork()成功则在父进程会返回新建立的子进程代码(PID),而在新建立的子进程中则返回 0。如果 fork 失败则直
接返回-1,失败原因存于 errno 中。

	pid_t pid = fork();

vfork  创建子进程

头文件:
  #include<unistd.h>
函数原型::pid_t vfork(void);
函数介绍: vfork()会产生一个新的子进程,其子进程会复制父进程的数据与堆栈空间,并继承父进程的用户代码,组代码,环境变量、已打开的文件代码、工作目录和资源限制等。数据空间与父进程共享(全局变量区 文本常量区)。先运行子进程,子进程结束后再运行父进程。
返回值:如果 vfork()成功则在父进程会返回新建立的子进程代码(PID),而在新建立的子进程中则返回 0。如果 fork 失败则
直接返回-1,失败原因存于 errno 中。

	pid_t pid = vfork();

system  Shell命令创建子进程

头文件:
  #include<stdlib.h>
函数原型:int system(const char * string);
参数介绍:
  string:可执行文件 路径+名字
函数介绍::system()会调用 fork()产生子进程,由子进程来调用/bin/sh-c string 来执行参数 string 字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用 system()期间 SIGCHLD 信号会被暂时搁置,SIGINT 和 SIGQUIT 信号则会被忽略。
返回值:如果 system()在调用/bin/sh 时失败则返回 127,其他失败原因返回-1。若参数 string 为空指针(NULL),则返回非零值。如果 system()调用成功则最后会返回执行 shell 命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh 失败所返回的 127,因此最好能再检查 errno 来确认执行成功。

	system("./fun");

execl  创建子进程

头文件:
  #include<unistd.h>
函数原型:int execl(const char * path,const char * arg,…);
参数介绍:
  path:文件路径+名字
  arg:所要传送的参数,最后必须使用NULL作为结束
函数介绍:execl用另一个新程序替换了当前进程的正文、数据、堆和栈段,进程ID不变。
返回值:如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于 errno 中。

四个创建子进程函数的区别

函数复制父进程数据是否有自己的独立空间修改数据影响父进程是否创建新进程
fork
vfork
system
execl

进程的退出

  进程退出三种方法:return、exit()、_exit()。第二种为常用。
三者的区别:
return:
  在函数中使用return语句可以退出当前函数并返回一个值给调用者,但不会结束整个进程。
exit():
  exit()是一个库函数,用于正常终止当前进程,并返回一个状态码给操作系统。它会执行一系列清理工作,如关闭文件、释放内存等,然后终止进程。
_exit():
   _exit()是一个系统调用,用于立即终止当前进程,不会执行任何清理工作。它直接通知操作系统终止进程,不会触发任何终止处理程序,也不会刷新缓冲区或关闭文件。通常情况下,应该在使用fork()创建子进程后,使用_exit()来终止子进程。

进程退出产生的相关问题

孤儿进程

孤儿进程的本质上还是个普通的进程,是指一个父进程退出,而它的一个或者多个子进程还在运行,那么这些子进程就称为孤儿进程。孤儿进程会被系统指定的进程所收养,并由收养孤儿进程的进程对他们进程完成状态收集工作。注:在“红帽 Linux 系统”中,孤儿进程将被“init 进程(进程号为 1)”的进程所收养,但是在“乌班图 Linux系统中”,是由“upstart 进程”所收养。

僵尸进程

Linux 的进程在结束的时候不会对自己的资源进行清零,只有父进程结束时才会对子进程的资源进程清零。僵尸进程是指子进程先于父进程退出,父进程退出的时候没有回收子进程退出状态的资源(task_struct),因此子进程就称为僵尸进程(孩子寄了,父亲没有收s)。写程序时要尽量避免出现僵尸进程(系统垃圾),利用等待进程退出函数可以解决僵尸进程问题。

下面提供了一些解决措施

1)父进程使用wait()或waitpid()系统调用来回收子进程的资源,避免子进程成为僵尸进程。
2 )使用信号处理机制,在父进程中注册SIGCHLD信号处理函数,当子进程终止时会触发该信号,父进程可以在信号处理函数中回收子进程的资源。
3 )使用守护进程来创建子进程,守护进程会负责回收子进程的资源,避免子进程成为僵尸进程。

参考文献

文章 进程调度算法 和 进程状态 部分内容参考于 《计算机操作系统(第 三 版)》 汤小丹 梁红兵 哲凤屏 汤子瀛 编著
(想要资源的可以私信我,我有PDF版本)

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

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

相关文章

RT-DETR算法优化改进:Backbone改进 | HGBlock完美结合PPHGNetV2 GhostConv

💡💡💡本文独家改进: GhostConv助力RT-DETR ,HGBlock与PPHGNetV2 GhostConv完美结合 推荐指数:五星 HGBlock_GhostConv | 亲测在多个数据集能够实现涨点 RT-DETR魔术师专栏介绍: https://blog.csdn.net/m0_63774211/category_12497375.html ✨✨✨魔改创新RT-…

202311.13 windows通过vscode ssh远程连接到Ubuntu 连接失败 waiting for server log

关闭VScode时没有关闭终端的Ubuntu进程&#xff1f; 导致重启后不能正常连接到Ubuntu了 Windows 系统自带的cmd终端通过ssh 可以连接 应该是vscode里对Ubuntu 的服务器端配置出了问题 参考&#xff1a;记录 VSCode ssh 连接远程服务器时出错及解决方法 在Windows 的vscode里面执…

jumpserver任意密码重置漏洞-CVE-2023-42820

目录 jumpserver 环境搭建 这里用的是vulhub靶场 进入 jumpserver 的目录 修改配置文件 config.env 里面的 DOMAINS 参数为kali的地址 运行环境&#xff0c;第一次运行的话会拉取文件&#xff0c;要耐心等待。 命令&#xff1a; 查看docker容器 命令&#xff1a; 用浏…

【兔子王赠书第7期】机器学习与人工智能实战:基于业务场景的工程应用

文章目录 写在前面机器学习推荐图书写给读者前言本书面向的读者我为什么要写这本书运行本书的示例代码本书导航本书采用的约定使用代码示例 推荐理由粉丝福利写在后面 写在前面 新的一周开始啦&#xff0c;本周博主给大家带来《机器学习与人工智能实战&#xff1a;基于业务场景…

C语言ZZULIOJ1149:组合三位数之二

题目描述 把1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6&#xff0c;7&#xff0c;8&#xff0c;9&#xff0c;组成三个三位数&#xff08;每个数只能用一次&#xff09;,第二个数是第一个数的2倍&#xff0c;第三个数是第一个数的3倍&#xff0c;这三…

Autosar模块介绍:Memory_5(FEE-Flash模拟EE)

上一篇 | 返回主目录 | 下一篇 Autosar模块介绍&#xff1a;Memory_5(FEE-Flash模拟EE 1 基本术语解释2 Fee组成结构图3 Fee基本操作3.1 寻址方式和段划分3.2 地址计算3.3 擦除循环限制3.4 处理立即数据3.5 管理块的正确信息 4 Fee常用操作时序4.1 Fee_Init4.2 Fee_SetMode4.…

如何在OpenWrt上部署uhttpd搭建web服务器,并实现公网远程访问

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

【Python 算法】双向迪杰斯特拉算法 Python实现

双向迪杰斯特拉算法Python实现 文章目录 双向迪杰斯特拉算法Python实现简介双向迪杰斯特拉算法优势局限性算法的基本步骤终止条件 基本步骤伪代码Python 实现 简介 双向迪杰斯特拉算法&#xff08;Bi Directional Dijkstra Algorithm&#xff09;是一种用于在加权图中查找两个…

6 Spring循环依赖

什么是循环依赖&#xff1f; // A依赖了B class A{ public B b; } // B依赖了A class B{ public A a; } 如果不考虑Spring&#xff0c;循环依赖并不是问题&#xff0c;因为对象之间相互依赖是很正常的事情 A a new A(); B b new B(); a.b b; b.a a; 这样&#xff0c;A&a…

初认识vue,v-for,v-if,v-bind,v-model,v-html等指令

vue 一.vue3介绍 1.为什么data是函数而不是对象? 因为vue是组件开发,组件会多次复用,data如果是对象,多次复用是共享,必须函数返回一个新的对象 1. 官网初识 Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS …

stm32控制舵机sg90

一、sg90简介 首先介绍说一下什么是舵机。舵机是一种位置&#xff08;角度&#xff09;伺服的驱动器。适用于一些需要角度不断变化的&#xff0c;可以保持的控制系统。sg90就是舵机的一种。 舵机的工作原理比较简单。舵机内部有一个基准电压&#xff0c;单片机产生的PWM信号通…

postswigger 靶场(CSRF)攻略-- 3.令牌验证

靶场地址&#xff1a; https://portswigger.net/web-security/csrf 令牌(token) 验证取决于令牌(token) 的存在 题目中已告知易受攻击的是电子邮件的更改功能&#xff0c;而目标是利用 csrf 漏洞更改受害者的电子邮件地址&#xff0c;最后给出了登录凭据&#xff1a;wiener:pet…

接口优化技巧,确实很优雅

针对疫情影响企业收入资源短缺一些老项目,做了许多降本增效的事情,其中发现最多的就是接口耗时过长的问题,就集中搞了一次接口性能优化。 二、接口优化方案执行 1、批处理 批量思想:批量操作数据库,项目往往有需要批量插入操作,比如商品,品格,价格等,可以在批处理执…

计算机毕业设计 基于Vue篮球联盟管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

YOLO的bounding boxes

YOLO使用了 77 网格 (SS)、2 个bounding boxes (B2) 和 20 个类别 ©。 1.YOLO将输入的图片resize成448 x 448&#xff0c;并且为 S x S&#xff08;S 7&#xff09;个grid&#xff0c;如果物体的中心落入该grid中&#xff0c;那么该grid就需要负责检测该物体。 2.对于每…

行业寒冬下,给软件测试工程师or功能测试的一些建议

​行业寒冬下&#xff0c;给软件测试工程师的一些建议 【文章末尾给大家留下了大量的福利】 国内的互联网行业发展较快&#xff0c;所以造成了技术研发类员工工作强度比较大&#xff0c;同时技术的快速更新又需要员工不断的学习新的技术。因此淘汰率也比较高&#xff0c;超过…

No191.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

时钟丢失监控机制

文章目录 前言一、分析芯片手册1、6.2.4 Clock monitoring2、28.1.5 System clock and clock monitor requirement3、分析寄存器1) SCG_SOSCCSR[SOSCCM]2) SCG_SOSCCSR[SOSCCMRE] 二、EB配置1、检查复位源2、配置时钟监控 三、结果验证总结 前言 本文章主要基于恩智浦 S32K14x…

【代码随想录】算法训练计划20

1、654. 最大二叉树 题目&#xff1a; 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。 递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上 构建…