(八)Linux的进程与线程

多任务处理是指用户可以在同一时间内运行多个应用程序,每个正在执行的程序被称为一个任务。一个任务包含一个或多个完成独立功能的子任务,其中子任务可以是进程或线程。Linux就是一个支持多任务的操作系统,比起单任务系统它的功能增强许多。

一.进程

进程:一个具有独立功能的程序在某个数据集合上的一次动态执行过程,它是操作系统进行资源分配和调度的基本单元。一次任务的运行可以激活多个进程,进程相互合作来完成该任务的一个最终目标。
进程和程序区别:
1)程序是一段静态的代码,是保存在非易失性的存储器上的指令和数据的有序集合,没有任何执行的概念。
2)进程是一个动态的概念,它是程序的一次执行过程,包括了动态创建、调度、执行和消亡的整个过程,它是程序执行和资源管理的最小单位。
Linux系统中主要下面几种类型的进程。

进程说明
交互性进程常与用户进行交互,需要等待用户的输入。当接收到用户的输入之后进程立即响应,如Shell命令进程、文本编辑器和图形应用程序运行
批处理进程不用进行交互,通常在后台运行,不必快速响应,不会优先调度。如编译器的编译操作、数据库搜索引擎
守护进程一直在后台运行,和任何终端都不关联。通常系统启动时开始执行,系统关闭时才开始

进程具有以下几个主要性质

性质说明
并发性系统多个进程可以同时并发执行,相互之间不受干扰
动态性进程都有完整的生命周期,而且在进程的生命周期中,进程状态是不断变化的,进程具有动态的地址空间
交互性进程在执行过程中会与其它进程发生直接和间接的通信,如进程同步和进程互斥等,需要为此添加一定的进程处理机制
独立性进程是相对完整的资源分配和调度的基本单元,各个进程的地址空间是相互独立的

进程不但包括程序的指令和数据,而且包括程序计数器和处理器的所有寄存器以及存储临时数据的进程堆栈。Linux内核取得处理器的控制权,按照某种调度算法将处理器分配给某个正在等待执行的进程。内核将所有的进程存放在双向循环链表(进程链表)中,链表的每一项都是task_struct,称为进程控制块的结构,其在<include/Linux/sched.h>文件中定义。task_struct 内核比较大,它能完整描述一个进程,如进程的状态、进程的基本信息、进程标识符、内存相关信息、父进程相关信息、与进程相关的终端信息、当前工作目录、打开的文件信息、所接收的信号信息等。
task_struct结构中最为重要的两个域:state(进程状态)和pid(进程标识符)
(1)进程状态
Linux中进程的几个主要状态如下:

进程状态说明
运行状态进程正在运行,或者正在运行队列中等待调度
可中断的阻塞状态进程处于阻塞(睡眠)状态,正等待某些事情发生或者占用某些资源。处于这种状态的进程可被信号中断。接收到信号可被唤醒。唤醒之后变为运行状态
不可中断的阻塞状态不会处理信号,只有等待的事情发生时,进程才能被显式呼叫唤醒
暂停状态进程的执行被暂停,当收到暂停信号才进入暂停
僵死状态子进程运行结束,父进程未退出,并且未使用wait函数族等系统来调用来回子进程的退出状态。
消亡状态最终状态,父进程调用wait函数族回收后,子进程彻底由系统删除,不可见。

(2)进程标识符与进程命令
Linux内核通过唯一的进程标识符PID来标识每一个进程。系统创建的进程数目有限制,可以查看/proc/sys/kernel/pid_max/来确定上限。

命令说明
current->pid ,top用来记录正在运行的进程
for_each_process,ps -l/-e/-f查看所有进程
getpid获得当前进程的进程号
getppid获得当前进程的父进程号
jobs查看后台进程
bg将挂起的进程在后台运行
fg把后台运行的进程放到前台运行
nice按用户指定的优先级运行进程
renice改变正在运行进程的优先级
/proc查看进程详细信息

(3)进程的创建、执行和终止
首先在新的地址空间里创建进程、读入可执行文件,最后再开始执行。Linux中进程的创建分解到fork()和exec函数族执行。fork()通过复制当前进程创建一个子进程,exec函数族负责读取其载入地址空间开始运行。
子进程与父进程的区别:不同的PID、PPID和某些资源及统计量
进程终止时系统需保证进程所占用的资源回收,并通知父进程。Linux首先把终止的进程设置为僵死状态,进程无法运行,只能为父进程提供信息。父进程在某个时间调用wait函数族,回收子进程的退出状态,然后子进程占用的所有资源被释放。
(4)进程的内存管理
Linux操作系统采用虚拟内存空间管理技术,使得每个进程都具有独立的地址空间,该地址空间是大小为4GB的线性虚拟空间。4GB的进程地址空间分为用户空间和内核空间。用户空间是0~3GB,内核地址空间占3-4GB。用户进程只能访问用户空间的虚拟地址,只有使用系统调用时才能访问内核空间。
用户空间包括以下几个功能区域(称段)

说明
只读段具有只读性质,包括程序代码(.init和.text)和只读数据 (.rodata)
数据段存放的是全局变量和静态变量,初始化段(.data和.bss)和未初始化段
由系统自动分配释放存放函数的参数值、局部变量的值和返回地址等
存放动态分配的数据,一般由程序员动态分配和释放,若不释放,程序结束可由系统回收
共享库的内存映射区域Linux动态链接器和其它共享库代码

二.进程编程

(1)进程创建:fork()函数
fork()函数用于从一个已存在进程中创建一个新进程,新进程是原进程的子进程。
父进程:进程上下文、代码段、进程堆栈、内存信息、打开的文件描述符、信号处理函数、进程优先级、进程组号、当前工作目录、根目录、资源限制和控制终端等
子进程:除父进程还有它的进程号、资源使用和计数器等
父子进程的区别:fork()的返回值不同。父进程返回子进程的进程号,子进程返回0

#include<sys/types.h>
#include<unistd.h>
pid_t fork()
返回值:子进程PID(大于0的整数)->父进程:0->子进程:-1->出错
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>int main(void){pid_t ret;ret=fork();if(ret== -1)
{perror("fork error");return -1;
}
else if (ret == 0)
{printf("In child process!!ret is %d,My PID is %d\n",ret,getpid());
}
else 
{printf("In parent process !! ret is %d,My PID is %d\n",ret,getpid());
}
return 0;
}
In parent process !! ret is 32189,My PID is 32188
In child process!!ret is 0,My PID is 32189

若父进程先结束,子进程成为孤儿进程,被init进程收养,子进程变成后台进程
若子进程先结束,父进程如果没有及时回收,子进程变成僵尸进程

(2)exec函数族
exec函数组提供了一个在进程中执行另一个程序的方法,它可以根据指定文件名或者目录名找到可执行文件,并用它来取代当前进程的数据段、代码段和堆栈段。执行完后,当前进程除了进程号外,其它内容都被替换。
在Linux中使用exec函数族主要两种情况:
1)当进程认为自己不能再为系统和用户做出任何贡献时,就可以调用exec()函数族中的任意一个函数让自己重生。
2)如果一个进程想执行另一程序,那么它就可以调用fork()函数新建一个进程,然后调用exec( )函数族中的任意一个函数,这样看起来就像通过执行应用程序而产生了一个进程。
进程调用exec函数族执行某个程序
进程当前内容被指定的程序替换
实现让父子进程执行不同的程序:
父进程创建子进程
子进程调用exec函数族
父进程不受影响

#include<unistd.h>
int execl(const char *path ,const char *arg,...);
int execv(const char *path ,char *const argv[]);
int execle(const char *path,const char *arg,...,char *const envp[]);
int execve(const char *path,const char *arg,...,char *const envp[]);
int execlp(const char *file,const char *arg,...);
int execvp(const char *file,char *const argv[]);
返回值-1:出错
函数名含义
前4位exec
第五位l:参数传递为逐个列举,v:参数传递为构造数组指针数组
第六位e:可传递新进程环境变量,p:可执行文件查找方式为文件名

实际上,这6个函数中真正的系统调用只有execve(),其它5个都是库函数,它们最终都会调用execve()这个系统调用。在使用exec函数族时,要加入错误判断语句。exec很容易执行失败,常见原因如下:
1)找不到文件或路径,此时errno被设置为ENOENT
2)数组argv和envp忘记用NULL结束,此时errno被设置为EFAULT
3)没有对应可执行的运行权限,此时errno被设置为EACCES

执行ls命令,显示/etc目录下所有文件的详细信息if  (execl(/bin/ls”, “ls”,-a”,-l”,/etc”, NULL) < 0) {perror(“execl”);}  if  (execlp(“ls”, “ls”,-a”,-l”,/etc”, NULL) < 0) {perror(“execlp”);}  
执行ls命令,显示/etc目录下所有文件的详细信息char  *arg[] = {“ls”,-a”,-l”,/etc”, NULL};if  (execv(/bin/ls”, arg) < 0) {perror(“execv”);}  if  (execvp(“ls”, arg) < 0) {perror(“execvp”);}  

(3)进程退出:exit()和_exit()
exit()和_exit()函数都是用来终止进程的。当程序执行到exit()和_exit()时,进程会无条件地停止剩下的所有操作,清除各种数据结构,并终止本进程的运行。但是,这两个函数还是有区别的。_exit()函数的作用是直接使进程停止运行,清除其使用的内存空间,并清除其在内核中的各种数据结构;exit()函数则在这些基础上做了一些包装,在执行退出之前加入了若干道工序。它们最大区别是终止当前进程之前,有无进行清理I/O缓冲。

#include<stdlib.h>
void exit(int status);返回值:0表示正常结束,其它表示进程非正常结束
#include<unistd.h>
void _exit(int status);
#include <stdio.h>#include <stdlib.h>int main(void) {printf(“this process will exit”);exit(0);printf(“never  be  displayed”);}```c
./a.out  this process will be exit

(4)进程回收:wait()和waitpid()
wait()函数用于使父进程(调用wait()的进程)阻塞,直到一个子进程结束或者该进程接收到一个指定信号为止。如果该父进程没有子进程或者他的子进程已经结束,则wait()会返回-1。waitpid的作用和wait()一样,但它并不一定等待第一个终止的子进程。waitpid()有若干个选项,可以提供一个非阻塞的wait()功能。
子进程结束时由父进程回收,孤儿进程由init进程回收,若没有及时回收会出现僵尸进程。

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int *status);
成功:已回收的子进程的进程号
失败:-1
#include<sys/types.h>
#include<sys/wait.h>
pid_t waitpid(pid_t pid,int *status,int options);
pid>0:回收进程ID等于pid的子进程
pid=-1:回收任何一个子进程
pid=0:回收其组ID等于调用进程的组ID的任一子进程
pid<-1:回收其组ID等于pid的绝对值的任一子进程
options:WNOHANG->若指定的子进程没有结束,则waitpid()不阻塞而立即返回,此时返回值为0
option:WUNTRACED->为了实现某种操作,由pid指定的任一子进程已暂停,且其状态自暂停以来还未报告过,则返回其状态。
>0:已经结束运行的子进程的进程号
0:使用选项WNOHANG且没有子进程退出
-1:出错
waitpid(pid, &status, 0);waitpid(pid, 

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

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

相关文章

nodejs微信支付安全证书下载,亲测有效

微信支付是目前非常流行的支付方式之一&#xff0c;很多开发者在集成微信支付时需要下载并使用微信支付的安全证书。本文将详细介绍如何在Node.js环境中下载微信支付安全证书&#xff0c;并提供一个亲测有效的示例代码。 前置条件 在开始之前&#xff0c;请确保你已经具备以下…

3d渲染软件有哪些(1),渲染100邀请码1a12

3D渲染是把三维模型转成2D图像的过程&#xff0c;领域不同常用的软件也不一样&#xff0c;今天我们就简单介绍几个。 在介绍前我们先推荐一个设计人员常用到的工具&#xff0c;就是网渲平台渲染100&#xff0c;通过它设计师可以把本地渲染放到云端进行&#xff0c;价格也不贵&a…

永洪bi里topN的设置/用法

要实现的效果&#xff1a;实现通过输入参数&#xff0c;进行图表top的排序筛选 图示&#xff1a; 筛选前&#xff1a; 输入3&#xff0c;看top3的值&#xff1a; 输入-3&#xff0c;看倒数3个的值&#xff1a; 设置步骤&#xff1a; 1️⃣&#xff1a;添加一个“文本参数组件…

二叉搜索树详解

一、二叉搜索树的概念 二叉搜索树又名二叉排序树以及二叉查找树&#xff0c;它是一颗空树或者是具有以下性质的二叉树 *若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 *若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 *它…

昂科烧录器支持KIOXIA铠侠的可编程只读存储器TH58NVG4S0HTAK0

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中KIOXIA铠侠的电可擦除可编程只读存储器TH58NVG4S0HTAK0已经被昂科的通用烧录平台AP8000所支持。 TH58NVG4S0HTAK0是一个单一的3.3V 16Gbit&#xff08;18253611008位&#xff…

QT拖放事件之一:初识拖放4大事件处理函数

0、拖放 两个动作,合在一起称之为拖放事件; 拖:就是拖着走; 放:就是拖着走,然后松开鼠标了,释放了,这就是放; 注意:放:拖着的东西要放在什么地方??? 假如,我将一个记事本拖着跑,然后放到一个Widget窗口上,那么为了使得Widget能感知相应的事件(拖着进入事件…

智慧城市低空+AI视频智能监控:构建新时代安全防线

随着科技的飞速发展&#xff0c;智能监控技术已经广泛应用于各个领域&#xff0c;从城市治理到工业生产&#xff0c;从公共安全到环境监测&#xff0c;都发挥着越来越重要的作用。而在低空领域&#xff0c;AI视频智能监控方案的建设更是成为了一个热点话题。 一、低空AI视频智…

设计模式原则——迪米特法则原则

设计模式原则 设计模式示例代码库地址&#xff1a; https://gitee.com/Jasonpupil/designPatterns 迪米特法则原则&#xff1a; 意义在于降低类之间的耦合。由于每个对象尽量减少对于其他对象的了解&#xff0c;因此&#xff0c;很容易使得系统的功能模块功能独立&#xff…

[论文笔记]Mixture-of-Agents Enhances Large Language Model Capabilities

引言 今天带来一篇多智能体的论文笔记&#xff0c;Mixture-of-Agents Enhances Large Language Model Capabilities。 随着LLMs数量的增加&#xff0c;如何利用多个LLMs的集体专业知识是一个令人兴奋的开放方向。为了实现这个目标&#xff0c;作者提出了一种新的方法&#xf…

Erpnext安装

Erpnext安装 环境要求 Ubuntu 23.04 x86_64 Python 3.10.12 pip 23.0.1 node v18.16.0 npm 9.5.1 yarn 1.22.22 MariaDB 10.11.2 Redis 7.0.8 wkhtmltox 0.12.6.1 bench 5.22.6环境安装 Reids 安装 // 安装7.0.8 也可不指定版本 直接执行 sudo apt install redis-server s…

Spring Boot 3 搭建

1、jdk 17 2、spring boot 3.1.7 3、pom.xml <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xs…

在线客服源码系统全端通用 源码完全开源可以二次开发 带完整的安装代码包以及搭建教程

系统概述 在线客服源码系统采用了先进的技术架构&#xff0c;包括前端界面、后端服务、数据库等部分。前端界面采用了响应式设计&#xff0c;能够自适应不同的设备屏幕尺寸&#xff0c;为用户提供良好的使用体验。后端服务采用了高性能的服务器架构&#xff0c;确保系统的稳定…

【面向对象】复习(三)

this指针 本职&#xff1a;指针常量&#xff0c;指向当前对象 不能访问静态成员&#xff0c;因为静态成员属于类&#xff0c;this指针属于对象 不要返回局部变量的引用或指针 int f(){ int a1; return a;}//a是函数外的&#xff0c;函数结束不释放 A * f(A & a){return…

QT学习积累——在C++中,for循环中使用``与不使用``的区别和联系

目录 引出使用&与不使用&除法的一个坑 总结自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.进行触发 自定义信号重载带参数的按钮触发信号触发信号拓展 lambda表达式返回值mutable修饰案例 引出 QT学习积累——在C中&#xff0c;for循环中使用&与不使用&的…

即时发布,市场担忧导致比特币和以太坊全线暴跌

来源:币界网 作者:636Marx 币界网新闻 – 2024 年 6 月 25 日– 数字货币市场形势急转直下&#xff0c;两种主力的数字货币比特币和以太坊的价格大幅下跌&#xff0c;给数字货币市场带来冲击。比特币再次触及$60,000美元关口&#xff0c;而以太坊反弹乏力&#xff0c;在 3,300…

PointCloudLib (多线程)快速双边滤波 C++版本

0.实现效果 原始点云 和滤波后的点云对比 1.算法原理 PCL(Point Cloud Library)快速双边滤波是一种高效的点云数据滤波方法,它基于传统双边滤波算法进行了改进,通过引入近似方法加速计算过程。以下是关于PCL快速双边滤波的详细回答: 1. 基本原理 空间滤波:在点云中,相…

详解 ClickHouse 的 MaterializeMySQL 引擎

注意与 ClickHouse 的 MySQL 表引擎区分开 一、概述 ClickHouse 20.8.2.3 版本新增加了 MaterializeMySQL 的 database 引擎&#xff0c;该 database 能映射到 MySQL 中的某个 database &#xff0c; 并自动在 ClickHouse 中创建对应的 ReplacingMergeTree。ClickHouse 服务做…

Verilog的逻辑系统及数据类型(一):四值逻辑系统

目录 1. Verilog采用的四值逻辑系统2.主要数据类型2.1 net&#xff08;线网&#xff09;2.2 寄存器类 &#xff08;register)2.3 Verilog中net和register声明语法2.3.1 net声明2.3.2 寄存器声明 2.4 选择正确的数据类型2.5 选择数据类型时常犯的错误2.5.1 信号类型确定方法总结…

【嵌入式DIY实例】-Nokia 5110显示BME280传感器数据

Nokia 5110显示BME280传感器数据 文章目录 Nokia 5110显示BME280传感器数据1、硬件准备与接线2、代码实现本文将介绍如何使用 ESP8266 NodeMCU 板(ESP12-E 模块)和 BME280 气压、温度和湿度传感器构建一个简单的本地气象站。 NodeMCU 从 BME280 传感器读取温度、湿度和压力值…

2024广东省职业技能大赛云计算赛项实战——集群部署GitLab Runner

集群部署GitLab Runner 前言 题目如下: 部署GitLab Runner 将GitLab Runner部署到gitlab-ci命名空间下&#xff0c;Release名称为gitlab-runner&#xff0c;为GitLab Runner创建持久化构建缓存目录/home/gitlab-runner/ci-build-cache以加速构建速度&#xff0c;并将其注册到…