Linux系统编程之进程基础知识

概述

        在Linux系统中,进程是指一个正在运行的程序实例。每个进程都有一个唯一的进程标识符,即PID,操作系统通过这个PID来唯一识别和管理各个进程。进程不仅仅是程序代码的运行实例,它还包含了程序运行时所需的各种资源,包括:内存空间、文件描述符、输入输出设备等。

进程的组成

        一个Linux进程主要由以下几个部分组成。

        程序段:进程执行的机器指令,通常是从磁盘或Flash上的可执行文件加载到内存中的。

        数据段:包含全局变量和静态变量,通常也被加载到内存中。

        :动态分配的内存区域,用于存储动态分配的数据结构,比如:通过malloc或new分配的内存。

        :用于存储函数调用时的局部变量和函数参数,每次函数调用都会在栈上分配一个新的栈帧。

        文件描述符表:用于记录进程打开的文件和网络连接等,每个进程都有一个文件描述符表。

        进程控制块:英文全称为Process Control Block,通常简写为PCB。操作系统为每个进程维护的一个数据结构,记录了进程的所有相关信息,包括PID、状态、内存分配情况等。

进程的状态

        Linux进程的生命周期是指从进程被创建开始,到进程终止并释放所有资源为止的整个过程。在这个过程中,进程会经历不同的状态,并随着系统环境和任务需求的变化而在这些状态之间转换。

        一个典型的Linux进程,其生命周期通常包括以下几个阶段。

        创建:通过fork系统调用,创建一个新的进程。

        执行:进程在CPU上执行,可能经历多次状态转换。

        阻塞:进程因等待I/O操作或其他事件,暂停执行。

        终止:进程正常结束,或因错误而终止。

        回收:父进程通过wait或waitpid系统调用,回收子进程的资源。

        在Linux系统中,进程可以处于以下几种状态之一。

        就绪状态:进程已经准备好运行,等待CPU时间片。

        运行状态:进程正在CPU上执行。

        阻塞状态:进程因为等待某些事件的发生而暂停运行,如等待I/O操作完成。

        终止状态:进程已经完成或者因错误而终止。

        僵尸状态:进程已经结束,但其父进程尚未调用 wait 或 waitpid 函数回收其资源。

        停止状态:进程被暂停执行,通常是因为接收到 SIGSTOP 或 SIGTSTP 信号。

        进程的上述状态之间可以互相转换,常见的状态转换如下。

        就绪 -> 运行:当进程被调度程序选中,并分配到CPU上执行时,从就绪状态转换为运行状态。

        运行 -> 就绪:当进程的时间片用尽,或被更高优先级的进程抢占时,从运行状态转换为就绪状态。

        运行 -> 阻塞:当进程等待I/O操作完成,或其他事件发生时,从运行状态转换为阻塞状态。

        阻塞 -> 就绪:当进程等待的事件发生后,从阻塞状态转换为就绪状态。

        运行 -> 终止:当进程正常结束,或因错误终止时,从运行状态转换为终止状态。

        终止 -> 僵尸:当进程结束,但父进程尚未回收其资源时,从终止状态转换为僵尸状态。

        运行 -> 停止:当进程接收到SIGSTOP或SIGTSTP信号时,从运行状态转换为停止状态。

        停止 -> 运行:当进程接收到SIGCONT信号时,从停止状态转换为运行状态。

        为了更清晰地查看进程状态之间的转换过程,可参考下面的状态转换图。

        如果想查看进程的当前状态,可以使用ps、top等命令。比如:使用ps aux命令可以查看系统中所有进程的详细信息,包括:状态、PID、CPU使用率、内存使用率等。

进程控制块

        进程控制块,即PCB,是操作系统为每个进程维护的一个数据结构,记录了进程的所有相关信息。PCB是系统感知进程存在的唯一标志,系统通过PCB来管理和控制进程。PCB可以被操作系统中的多个模块读取或修改,比如:调度程序、资源分配程序、中断处理程序等。这些模块通过访问或修改PCB,来管理和控制进程的执行状态和资源分配情况。

        PCB中包含的主要信息如下。

        进程标识符:即PID,唯一标识进程的整数。PID在任何时刻都是唯一的,但可以重用。当进程终止并被系统回收后,其PID可以被其他新创建的进程使用。

        进程状态:记录进程当前所处的状态。

        程序计数器:指向进程下一条要执行的指令。

        寄存器状态:保存进程的寄存器值,用于进程切换时恢复现场。

        内存管理信息:包括进程的虚拟地址空间、页表等。

        文件描述符表:记录进程打开的文件和网络连接等。

        优先级:用于调度程序确定进程的优先级。

        父进程ID:记录创建该进程的父进程的PID。

        子进程列表:记录该进程创建的所有子进程的PID。

        资源限制:包括进程可以使用的最大内存、文件描述符数量等。

// 进程控制块PCB
struct task_struct
{
    pid_t pid;  // 进程ID
    char comm[16];  // 进程名
    mm_struct *mm;  // 内存描述符
    files_struct *files;  // 文件描述符表
    fs_struct *fs;  // 文件系统信息
    signal_struct *signal;  // 信号处理信息
    thread_info *thread_info;  // 线程信息
    struct list_head tasks;  // 进程链表节点
    struct task_struct *parent;  // 父进程指针
    struct task_struct *children;  // 子进程链表头
    struct task_struct *sibling;  // 兄弟进程链表
    unsigned long state;  // 进程状态
    int priority;  // 进程优先级
    int nice;  // 进程的nice值
    int static_prio;  // 静态优先级
    int policy;  // 调度策略
    struct sched_param sched_param;  // 调度参数
    unsigned long flags;  // 进程标志
    unsigned long timeout;  // 超时时间
    unsigned long rt_priority;  // 实时优先级
    unsigned long deadline;  // 截止时间
    unsigned long runtime;  // 运行时间
    unsigned long vruntime;  // 虚拟运行时间
    unsigned long utime;  // 用户模式下的运行时间
    unsigned long stime;  // 内核模式下的运行时间
    unsigned long nvcsw;  // 自愿上下文切换次数
    unsigned long nivcsw;  // 非自愿上下文切换次数
    unsigned long start_time;  // 进程启动时间
    unsigned long exit_time;  // 进程退出时间
    // ...
};

进程调度

        Linux系统中的所有进程形成一个树状结构,称为进程树。进程树的根节点是进程ID为1的init进程,它是系统启动后的第一个进程,负责启动其他系统进程和服务。每个进程都可以创建子进程,子进程又可以创建自己的子进程,从而形成一个多级的进程树。

        Linux内核负责决定哪个进程何时获得CPU时间,调度算法决定了进程的优先级和执行顺序,常见的调度策略如下。

        先来先服务:英文全称为“First-Come, First-Served”,缩写为FCFS。FCFS是一种简单的调度算法,按照进程到达的顺序进行调度。第一个到达的进程最先执行,然后是第二个到达的进程,依此类推。FCFS算法逻辑简单,容易理解和实现。但不够公平,缺乏优先级。比如:如果一个长作业首先到达,它会占用CPU较长时间,导致后续到达的短作业等待时间过长。

        短作业优先:英文全称为“Shortest Job First”,缩写为SJF。SJF是一种基于进程预计执行时间的调度算法,优先调度执行时间较短的进程。SJF可以减少平均等待时间,提高系统的整体吞吐量。但必须预先知道或估计每个进程的执行时间,这在实际应用中可能难以实现。

        时间片轮转:英文全称为“Round Robin”,缩写为RR。RR是一种基于时间片的调度算法,每个进程轮流分配固定的时间片,时间片用尽后切换到下一个进程。这样,每个进程都能获得平等的CPU时间,避免了某些进程长时间占用CPU。RR适用于交互式系统,可以快速响应用户的输入,但频繁的上下文切换可能会增加系统开销。

        优先级调度:英文全称为“Priority Scheduling”,缩写为PS。PS根据进程的优先级进行调度,高优先级的进程优先获得CPU时间。它的特点是比较灵活,可以根据进程的重要性和紧急程度动态调整优先级。缺点是低优先级的进程可能会因为高优先级进程的存在,而长期得不到CPU时间。

        完全公平调度:英文全称为“Completely Fair Scheduler”,缩写为CFS。CFS是Linux内核从版本2.6.23开始采用的默认调度算法,其设计目标是:在所有可运行的任务之间公平地分配CPU时间,确保没有任务长期得不到处理。CFS的主要特点有以下几点。

        (1)公平性。CFS使用一个称为虚拟运行时间的概念来衡量任务的执行时间,虚拟运行时间反映了任务相对于其他任务的执行情况。另外,CFS使用红黑树来维护等待执行的任务列表。任务根据其虚拟运行时间进行排序,确保运行时间最少的任务优先得到CPU时间。

        (2)可预测性。CFS提供了确定性的响应时间,实时任务优先于普通任务执行,这对于需要及时响应的应用程序非常重要。

        (3)适应性。CFS能够动态调整其行为,以适应不同的工作负载,包括:交互式应用和批处理任务。在多核系统中,CFS尝试将任务分配到不同的核心上,以减少CPU的空闲时间。

        (4)调度延迟。CFS会设定一个目标调度周期(通常为100毫秒),并试图让所有任务在这个周期内至少执行一次。CFS还会动态调整每个任务的时间片,确保运行时间较少的任务获得更多的机会。

        (5)优先级支持。CFS根据nice值调整任务的权重,从而影响其虚拟运行时间。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LabVIEW发动机热磨合试验台

在汽车发动机的研发和质量控制中,发动机热磨合试验是关键环节。它能够检验发动机在实际运行条件下的性能,及时发现异响、振动、漏油等潜在问题。通过搭建基于LabVIEW的高效测试平台,可以显著提高发动机的可靠性和使用寿命。下面介绍LabVIEW开…

【C++】C++11新特性详解:可变参数模板与emplace系列的应用

C语法相关知识点可以通过点击以下链接进行学习一起加油!命名空间缺省参数与函数重载C相关特性类和对象-上篇类和对象-中篇类和对象-下篇日期类C/C内存管理模板初阶String使用String模拟实现Vector使用及其模拟实现List使用及其模拟实现容器适配器Stack与QueuePriori…

js+jquery实现经典推箱子游戏

纯前端项目,只使用html,css,js,jquery实现经典推箱子游戏,直接下载本地双击index.html即可运行体验。 游戏展示 开始界面 完成游戏 代码展示

【Pytest+Yaml+Allure】实现接口自动化测试框架

一、框架思想 requestsyamlpytestallure实现接口自动化框架。结合数据驱动和分层思想,将代码与数据分离,易维护,易上手。使用yaml编写编写测试用例,利用requests库发送请求,使用pytest管理用例,allure生成…

[HarmonyOS] 解决HMRouter路由地址无法抽取的问题

解决HMRouter路由地址无法抽取的问题 背景 最近开始学习HarmonyOS开发,搭建项目的时候采用了 HMRouter 路由框架,在项目里使用到路由跳转,官方链接在这: https://gitee.com/hadss/hmrouter/blob/master/HMRouterLibrary/README…

ElasticSearch学习了解笔记

搜索引擎的原理: 1、查询分析(自然语言处理)理解用户需求 2、分词技术 3、关键词搜索匹配 4、搜索排序 lucence Lucene 是一个成熟的权威检索库 Elasticsearch 的搜索原理简单过程是,索引系统通过扫描文章中的每一个词&#xff…

ffmpeg视频滤镜:提取缩略图-framestep

滤镜描述 官网地址 > FFmpeg Filters Documentation 这个滤镜会间隔N帧抽取一帧图片&#xff0c;因此这个可以用于设置视频的缩略图。总体上这个滤镜比较简单。 滤镜使用 滤镜参数 framestep AVOptions:step <int> ..FV....... set frame st…

【C++11】可变参数模板/新的类功能/lambda/包装器--C++

文章目录 一、可变参数模板1、基本语法及原理2、包扩展3、empalce系列接口 二、新的类功能1、默认的移动构造和移动赋值2、成员变量声明时给缺省值3、defult和delete4、final与override 三、STL中一些变化四、lambda1、lambda表达式语法2、捕捉列表3、lambda的应用4、lambda的原…

云网络基础- TCP/IP 协议

文章目录 典型服务模式TCP/IP 协议设置和查看IPIP地址的分类:IP地址组成: 网络位主机位组成克隆:产生一台新的虚拟机win2008 典型服务模式 • C/S,Client/Server架构 – 由服务器提供资源或某种功能 – 客户机使用资源或功能 TCP/IP 协议 • TCP/IP是最广泛支持的通信协议集合…

java基础知识(Math类)

引入&#xff1a;Math 类包含用于执行基本数学运算的方法&#xff0c;如初等指数、对数、平方根 import java.util.Math 1.abs绝对值 int abs Math.abs(-9); 2.pow求幂 double pow Math.pow(2,4); 3.向上取整 double ceil Math.ceil(3.9);//ceil 4 4.向下取整 dou…

什么是 WPF 中的依赖属性?有什么作用?

依赖属性&#xff08;Dependency Property&#xff09;是 WPF 的一个核心概念&#xff0c;它为传统的 .NET 属性提供了增强功能&#xff0c;支持绑定、样式、动画和默认值等功能。通过依赖属性&#xff0c;WPF 提供了一种灵活的数据驱动的方式来处理 UI 属性。 1. 什么是依赖属…

线性代数空间理解

学习线性代数已经很久&#xff0c;但是在使用过程中仍然还是不明所以&#xff0c;比如不知道特征向量和特征值的含义、矩阵的相乘是什么意思、如何理解矩阵的秩……。随着遇到的次数越来越多&#xff0c;因此我决定需要对线性代数的本质做一次深刻的探讨了。 本次主要是参考了3…

Jmeter的组件执行顺序

在 Apache JMeter 中&#xff0c;组件的加载和执行顺序遵循一定的规则&#xff0c;但有些组件在同一层级中可能会根据它们在测试计划中的位置来决定具体的执行顺序。以下是这些组件的大致加载和执行顺序&#xff0c;以及哪些组件属于同一层级&#xff1a; 线程组&#xff08;Th…

计算机网络八股整理(一)

计算机网络八股文整理 一&#xff1a;网络模型 1&#xff1a;网络osi模型和tcp/ip模型分别介绍一下 osi模型是国际标准的网络模型&#xff0c;它由七层组成&#xff0c;从上到下分别是&#xff1a;应用层&#xff0c;表示层&#xff0c;会话层&#xff0c;传输层&#xff0c;…

今天你学C++了吗?——C++中的类与对象(第二集)

♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…

【C++习题】14.滑动窗口_找到字符串中所有字母异位词

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a;图解 题目链接&#xff1a; 438. 找到字符串中所有字母异位词 题目描述&#xff1a; 解法 暴力解法&#xff1a; 字母排序后运用滑动窗口解题。 滑动窗口哈希表&#xff1a; 我们可以优化一下&am…

Spring Boot集成MyBatis-Plus:自定义拦截器实现动态表名切换

Spring Boot集成MyBatis-Plus&#xff1a;自定义拦截器实现动态表名切换 一、引言 介绍动态表名的场景需求&#xff0c;比如多租户系统、分表分库&#xff0c;或者不同业务模块共用一套代码但操作不同表。说明 MyBatis-Plus 默认绑定固定表名的问题。 二、项目配置 1. 集成 M…

深入探索API爬虫工作的技术难点与高效解决思路

在大数据与信息化高速发展的今天&#xff0c;API&#xff08;应用程序编程接口&#xff09;爬虫成为了数据收集与分析的重要工具。然而&#xff0c;API爬虫工作并非一帆风顺&#xff0c;它面临着诸多技术挑战。本文将深入探讨几个API爬虫工作的技术难点&#xff0c;并提出相应的…

css效果

css炫彩流光圆环效果 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><style>*{margin: 0;padding: 0;}body{width: 100%;height: 100vh;}.container{position: relative;width: 100%;height: 100vh…

arm Rk1126 编译Qt工程报错: Could not find qmake spec

首先修改qmake.conf文件&#xff0c;配置好正确的交叉编译工具&#xff1a; 然后执行编译&#xff1a; /opt/Rv1126/Rv1126-盒子代码/rv1126-qt5-sdk/bin/qmake untitled.pro 报错。 原因&#xff1a;中文路径。修改路径为英文路径即可