进程与线程(一)

进程与线程(一)

  • 理解什么是并发编程
  • 进程的相关概念
    • 什么是进程
    • 对比进程和程序
    • 理解进程是一个独立的可调度的任务
    • 理解进程是程序执行和资源管理的最小单位
    • 进程状态转换图
    • 进程的种类
  • 进程相关命令
    • 进程状态标志
    • ps命令
      • -aux:
      • -axj:(可以查看到进程的PPID)
      • pstree
      • kill命令
  • 进程相关的系统调用
    • 进程创建
      • fork()
      • vfrok()
      • fork和vfork的区别
      • 获取进程ID和父ID的方法
      • 进程的退出
  • 僵尸进程和孤儿进程
    • 僵尸进程
    • 孤儿进程
    • 回收僵尸进程的方法
      • wait阻塞回收子进程的退出资源
      • waitpid非阻塞回收子进程的退出资源

理解什么是并发编程

并发是什么?
—》多个任务同时运行
任务是什么?
—》就是一个应用程序
思考:程序是如何产生的?
—》程序:一组能被计算机直接识别的有序指令的集合
所以:程序是被编译生成的 eg:gcc test.c -o App (App就是一个程序)
程序在外存(U盘,硬盘)上存储(静态的概念)
一个程序一旦被运行起来,就会产生一个进程(动态的:被创建,被调度,被消亡)
总结:Linux下的多任务编程就是多进程/多线程去协同工作,将某一个事情搞定的过程该过程避免不了多进程/多线程之间数据交互的问题(进程间通信的技术)

进程的相关概念

什么是进程

概念:进程就是程序的一次动态执行过程

对比进程和程序

程序:一组存储在磁盘上的有序指令的集合,是一个静态且没有任何执行的概念
进程:运行一个程序,就会拥有一个进程,它是程序的一次动态执行过程,动态性:创建,调度,消亡

理解进程是一个独立的可调度的任务

一个进程是一个独立的个体,意味着拥有自己专属的地址空间
地址空间图解:
在这里插入图片描述
调度:调用进程/线程,调用动作是由CPU来完成的!
再次理解:
CPU调用进程/线程本质:执行它!
思考:Linux下如何实现多任务(并发编程)的?(借助于CPU调度)
注意:单核的CPU同一时刻只能处理一个进程/线程,并发如何实现?
—》Linux下实现并发的思想:引入“时间片”的概念时间片?
–》每一个任务,操作系统为其分配了一段执行的时间,在这段时间之内处理你,超时则下次再处理,时间片很小,小到用户都可能感知不到时间片的概念,因此每一个任务都会有一个时间片,他们之间采用时间片轮转的概念,被加入到一个循环队列中(注意:该资源队列并不遵循先进先出的原则,多个任务的调度的是随机的,且存在优先级的概念!),多个任务(程序的执行过程)存在状态的切换。

理解进程是程序执行和资源管理的最小单位

程序执行的最小单位:每运行一个程序,就会产生一个进程
资源管理的最小单位:每一个进程都会拥有一个独立的地址空间(资源)

进程状态转换图

进程的状态:运行态,就绪态,等待态,停止态,死亡态,僵尸态
图解:运行态,等待态,死亡态
在这里插入图片描述

进程的种类

(1)交互进程:该进程需要人机交互,用户需要给该进程一个信息的反馈。(shell终端)
(2)批处理进程:也称批处理文本或者批处理脚本,他们采用轮询的概念去依次执行。
(3)守护进程:也称“精灵进程”,“监测进程”,”后台进程“,不受终端的控制!运行在后台。

进程相关命令

进程状态标志

在这里插入图片描述

ps命令

作用:打印出当前运行的进程
使用ps命令时,一般都会搭配选项来使用:
常用的选项

-aux:

在这里插入图片描述

-axj:(可以查看到进程的PPID)

在这里插入图片描述
在这里插入图片描述

pstree

作用:以树形关系呈现当前终端所有进程的所属关系
在这里插入图片描述

kill命令

作用:发送信号
常用的:杀死进程
方法:kill -9 pid; //pid为需要杀死的进程ID号
Linux下共有64个信号:
在这里插入图片描述

进程相关的系统调用

明确:进程都是被进程创建出来的
1号进程:init进程
init进程创建出一个systemd进程!
终端也是一个进程,也是被创建出来的
故:想要得到一个子进程,就必须去创建!!!

进程创建

fork()

#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
功能:创建一个进程
参数:无参
返回值:pid_t是int的别名,含义:
小于0,代表创建子进程失败,可以打印错误码查看原因
等于0,是在子进程中返回的
大于0,是在父进程中返回的,且含义为子进程的ID号(PID)

在这里插入图片描述
验证子进程的数据段是也是拷贝于父进程的(fork()):
在这里插入图片描述
在这里插入图片描述
验证fork之前,子进程会悉数拷贝父进程的所有内容:fork之前父进程有的,子进程都会拷贝一份

在这里插入图片描述
在这里插入图片描述
fork()的原理:

调用进程(称为父进程)通过复制自己,创建出一个新进程(称为子进程),子进程获得父进程的数据空间、堆和栈的副本,即父子进程的空间是独立的,创建出的子进程从fork返回处开始运行。

总结fork():

fork创建的子进程:
1、会完美拷贝父进程中的所有资源(堆栈段,代码段,数据段…)
2、子进程从fork的下一句话开始,会存在父子进程,为了区分两个进程到底谁在执行?
—》通过返回值来判断:等于0(子进程在执行)。大于0(父进程在执行)
3、子进程永远都是在fork的下一句开始执行的!(会用到fork之前父进程定义过的一些资源。)、
4、父子进程的执行次序不确定的!
5、父子进程的地址空间独立,互不影响,父子进程可以被CPU进行调度。

vfrok()

#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void);
用法同fork()!!!

vfork()的原理

vfork()函数创建新进程时并不复制父进程的地址空间,刚开始是运行在父进程的地址空间上的,且保障了子进程会优先被执行,当子进程执行了exec或者exit之后,父进程才有可能被调度。如果在调用exec或者exit之前,子进程依赖于父进程的进一步动作,则会导致死锁!
注意:使用vfork函数之后,子进程内部必须使用exec或者exit函数,否则会造成死锁的现象。

fork和vfork的区别

1、
fork():子进程拷贝父进程的数据段,代码段
vfork():子进程与父进程共享数据段
2、
fork()父子进程的执行次序不确定
vfork()保证子进程先运行,在调用exec或exit之前与父进程数据是共享的,在它调用exec或exit之后父进程才可能被调度运行。
3、
vfork()保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁,所以使用vfork创建的子进程必须使用exec重新启动一个新的程序或者exit()使得子进程退出

获取进程ID和父ID的方法

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);//获取当前进程的ID号
pid_t getppid(void);//获取当前进程的父进程ID号

以上两个函数的返回值就是获取的ID号的结果!!!

进程的退出

_exit()函数的作用最为简单:直接使进程终止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;
exit()函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序。
exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是图中的"清理I/O缓冲"一项。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

僵尸进程和孤儿进程

僵尸进程

子进程先于父进程退出,而父进程没有回收子进程的退出资源(一小部分的PCB:struct_task的结构体),此时的子进程就会沦为僵尸进程!
僵尸进程的危害:内存泄漏,因此需要避免僵尸进程的产生!
如何避免僵尸进程产生?
----》子进程的退出资源本应该是父进程来回收,因此将回收子进程的退出资源这件事让父进程使用某种手段进行处理即可!

孤儿进程

父进程先于子进程退出,此时的子进程会沦为孤儿进程,会被systemd进程收养,孤儿进程没有任何坏处

回收僵尸进程的方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

wait阻塞回收子进程的退出资源

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, const char *argv[])
{//定义局部变量int a = 0;//使用fork来创建一个子进程pid_t pid = fork();if(pid < 0){perror("fork child process error");return -1;}else if(0 == pid){//子进程在执行代码while(1){a++;printf("子进程:a = %d\n",a);printf("I am child process!\n");sleep(1);}}else{//使用wait阻塞回收子进程的退出资源printf("等待回收子进程中......\n");pid_t exitPID = wait(NULL);//阻塞printf("exitPID = %d的子进程已被回收!\n", exitPID);//父进程在执行代码while(1){a++;printf("父进程:a = %d\n",a);printf("I am parent process!\n");sleep(1);}}printf("test!!!\n");return 0;
}

waitpid非阻塞回收子进程的退出资源

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{//定义局部变量int a = 0;//使用fork来创建一个子进程pid_t pid = fork();if(pid < 0){perror("fork child process error");return -1;}else if(0 == pid){//子进程在执行代码while(1){a++;printf("子进程:a = %d\n",a);printf("I am child process!\n");sleep(1);if(a >= 5){exit(0);//子进程主动退出 返回-1此时对方查看的是255}}}else{//父进程在执行代码while(1){printf("等待回收资源中...\n");//引入waitpid回收子进程的退出资源,关心子进程的退出状态int status;pid_t exitPID = waitpid(-1, &status, WNOHANG);if(exitPID < 0){perror("waitpid error");}else if(0 == exitPID){printf("未检测到有子进程结束...\n");}else{//判断子进程是正常退出还是异常退出if(WIFEXITED(status)){//进入if则代表正常退出printf("正常退出!\n");}else{printf("非正常退出!\n");}printf("已成功回收exitPID = %d的子进程资源!\n", \exitPID);//获取子进程的退出状态数值printf("退出状态数值:%d\n",WEXITSTATUS(status));}a++;printf("父进程:a = %d\n",a);printf("I am parent process!\n");sleep(1);}}printf("test!!!\n");return 0;
}

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

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

相关文章

浅析R16移动性增强那些事儿(DAPS/CHO/MRO)

R16移动性增强相关技术总结 Dual Active Protocol Handover Dual Active Protocol Handover意为双激活协议栈切换&#xff0c;下文简称DAPS切换&#xff0c;DAPS切换的核心思想是切换过程中&#xff0c;在UE成功连接到目标基站前继续保持和源基站的连接和数据传输&#xff0c;…

示波器眼图怎么看

目录 什么是眼图&#xff1f; 怎么看&#xff1f; 眼图的电压幅度&#xff08;Y轴&#xff09; 眼睛幅度和高度 信噪比 抖动 上升时间和下降时间 眼宽 什么是眼图&#xff1f; 眼图&#xff08;Eye Diagram&#xff09;是一种用于分析高速数字信号传输质量的重要工具。通…

OpenJDK优化技术之标量替换(Scalar Replacement)

标量替换 (SR) 是 OpenJDK 中一项强大的优化技术&#xff0c;旨在通过将复杂对象分解为更简单、更易于管理的标量变量来提高 Java 应用程序的性能。 1.前言 OpenJDK JVM 有两个即时编译器&#xff0c;C1 和 C2。C2 是一种应用许多优化来生成非常高效的编译版本程序的编译器。…

【全开源】Java共享台球室无人系统支持微信小程序+微信公众号+H5

智能引领台球新体验 一、引言&#xff1a;共享经济的新篇章 在共享经济的大潮中&#xff0c;各类共享服务层出不穷&#xff0c;为人们的生活带来了极大的便利。共享台球室作为其中的一员&#xff0c;以其独特的魅力吸引了众多台球爱好者的目光。而今天&#xff0c;我们要介绍…

【JavaScript脚本宇宙】JavaScript日期处理神器: 6款顶级库解析

提升编程效率&#xff1a;六个强大的JavaScript日期时间库介绍 前言 在信息化社会&#xff0c;日期和时间的处理是任何编程语言必不可少的部分。本文将介绍六个优秀的JavaScript日期和时间库&#xff0c;这些库各有特色&#xff0c;可以应对多样的使用场景。 欢迎订阅专栏&am…

RAG检索增强生成

Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks Lewis P, Perez E, Piktus A, et al. Retrieval-augmented generation for knowledge-intensive nlp tasks[J]. Advances in Neural Information Processing Systems, 2020, 33: 9459-9474.

【通信专题】I2C上拉电阻计算方法

I2C 通信总线是电子设计中常见的总线之一,由于 I2C 的硬件芯片内部为开漏输出,所以要求在外部增加一个上拉电阻,总线上拉电阻的选取受多个因素的影响,因此如何计算 I2C 总线的上拉电阻阻值成为硬件工程师在使用 I2C总统时需要关注的话题。 从本质上讲: I2C 总线电容和上升…

算法第三天力扣第69题:X的平方根

69. x 的平方根 (可点击下面链接或复制网址进行做题) https://leetcode.cn/problems/sqrtx/https://leetcode.cn/problems/sqrtx/ 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。 注意:不允许使用任何内…

密码和密钥的联系与区别

密码和密钥是两个非常重要的概念&#xff0c;但容易混淆这两者&#xff0c;以下内容介绍了它们的联系和区别&#xff1a; 一、定义 密码&#xff08;Password&#xff09;&#xff0c;在日常语境中&#xff0c;通常指的是个人为了验证自己的身份而设置的一段秘密的字符序列&am…

动态规划:优化问题求解的艺术

引言&#xff1a; 在计算机科学和数学中&#xff0c;动态规划是一种强大的算法设计技术&#xff0c;用于解决具有重叠子问题和最优子结构特性的复杂问题。动态规划不仅可以简化问题的求解过程&#xff0c;还能显著提高效率。本文将介绍动态规划的基本概念、工作原理、算法设计步…

周末总结(2024/06/01)

工作 人际关系核心实践&#xff1a; 要学会随时回应别人的善意。执行时间控制在5分钟以内 坚持每天早会打招呼 遇到接不住的话题时拉低自己&#xff0c;抬高别人(无阴阳气息) 工作上的要点 现状&#xff08;接受破烂现状&#xff0c;改变状态&#xff09; - 我很不满意现在的…

基于Qt GraphicView 解析 CIM/G 电力接线图文件

本文讲述了如何使用Qt的框架来渲染展示标准的CIM/G格式的图形文件&#xff0c;也就是公用信息模型&#xff08;common information model&#xff0c;CIM&#xff09;中的G文件部分的内容。这是一种电力系统图形的交换规则&#xff0c;用于电网图形交换。 [by amjieker] CIM/G …

【自动驾驶】点与向量从ego系转odometry系

1.点从ego系转odometry系(ego -> odometry) struct Point {float x;float y;float angle; }; Point trans; // is the odom to ego transform Point odom_coord; is the odom coord Point ego_coord; is the ego coordfloat odom_coord.x = (ego_coord.x - trans.x) * st…

Selenium番外篇文本查找、元素高亮、截图、无头运行

Selenium根据文本查找元素 ​ python def find_element_with_text(self, loc, attribute, text):try:WebDriverWait(self.driver, 5).until(EC.all_of(EC.text_to_be_present_in_element_attribute(loc, attribute, text)))element self.driver.find_element(*loc)if isinsta…

C++青少年简明教程:break语句、continue语句

C青少年简明教程&#xff1a;break语句、continue语句 break语句 只能用在switch语句和循环语句&#xff08;for循环、while循环和do-while循环&#xff09;中。作用&#xff1a;跳出switch语句或提前终止循环。 break语句的基本语法如下&#xff1a; break; break语句的示例…

Nutanix在.NEXT大会宣布AI战略升级:GPT-in-a-Box 2.0集成NVIDIA,强化企业级AI应用支持

Nutanix在巴塞罗那举行的.NEXT大会上宣布了一系列新动向&#xff0c;旨在借助与思科的合作、Broadcom收购VMware、生成式人工智能&#xff08;GenAI&#xff09;的兴起、容器化技术、PostgreSQL数据库的广泛应用以及绿色能源倡议&#xff0c;进一步扩大其在人工智能领域的影响力…

macbook配置前端环境:深度解析与实战指南

macbook配置前端环境&#xff1a;深度解析与实战指南 在数字时代的浪潮中&#xff0c;前端开发已成为构建互动、生动且富有吸引力的用户界面的关键。而MacBook&#xff0c;以其卓越的性能和稳定的系统&#xff0c;成为前端开发者们的首选工具。然而&#xff0c;对于初学者或新…

C# WinForm —— 26 ImageList 介绍

1. 简介 图片集合&#xff0c;用于存储图像的资源&#xff0c;并在关联控件中显示出来 可以通过 索引、键名 访问每张图片 没有事件 2. 属性 属性解释(Name)控件ID&#xff0c;在代码里引用的时候会用到,一般以 imgList 开头ClolorDepth用于呈现图像的颜色数&#xff0c;默…

函数:计算数组的元素和

一、计算数组的元素和 参数传递给函数时&#xff0c;实际上只有数组的首地址作为指针传递给了函数。 在函数定义中的int a[ ]等价于int *a。在只有地址信息的情况下&#xff0c;是无法知道数组里有多少个元素的&#xff0c;因此在计算数组中的元素和时&#xff0c;要加一个参…

jetson nano onnxruntime 安装

安装说明&#xff1a; onnxruntime 依赖cuda、cudnn版本&#xff0c;可onnxruntime查找对应关系。但可能会出现jetpack中的cuda和cudnn的版本无法查找到对应版本的onnxruntime的问题。 解决方法&#xff1a; 通过Jetson Zoo下载相应的whl包直接安装。