IO进程线程(六)进程
文章目录
- 一、进程状态
- (二)进程状态切换实例
- 1. 实例1
- 二、进程的创建
- (一)原理
- (二)fork函数--创建进程
- 1. 定义
- 2. 不关注返回值
- 3. 关注返回值
- (三) 父子进程的执行顺序
- (四)父子进程内存空间
- (五)使用实例
- 三、 getpid/getppid
- 四、孤儿进程
- 五、僵尸进程
- 三、进程退出exit/_exit函数
- (一)exit
- (二)_exit
- 四、进程回收资源
- (一)wait
- (二)waitpid
一、进程状态
可通过 man ps 查看
R (runing or runnable) 运行态或者可被运行态(在运行队列中)
S (interruptible sleep) 可被中断的休眠态
D (uninterruptible sleep) 不可被中断的休眠态
T (stopped by job control signal) 停止态
Z (("zombie") process)僵尸态
X (dead ) 死亡态(永远不会被看到)
I (Idle kernel thread) 空闲内核线程
进程的附加状态:
< 高优先级的进程
N 低优先级的进程
s (session leader)会话组组长
l (multi-threaded)进程中包含多线程
+ 前台进程组的进程
L 有页在内存中被锁定
(二)进程状态切换实例
1. 实例1
#include <stdio.h>int main(int argc, char const *argv[])
{int i=0;while(1){printf("%d\n",i++);sleep(1);}return 0;
}
① 该程序运行时,大部分时间在休眠,处于休眠态
./a.out 运行 ------ 前台运行

② 想让一个进程在后台运行
可以 在运行进程的命令后面加一个 & 如 ./a.out &

- 注:
- 前台运行时,终端会被该进程占用,无法继续接收命令
- 后台运行时,终端会被释放出来,可以接收命令
- 处于后台运行时,无法直接“CTRL+C”来结束进程,需要发送
kill -19 pid
③可以使用 kill -19 pid 给进程发19号信号让进程停止(T停止态)
也可以使用 ctrl+z 来停止进程(相当于给进程发kill -20 pid)
在被停止的进程的终端上使用 jobs -l 可以查看进程的作业号
- 注:此处必须在被停止的进程的终端上查看,其他终端无法查看

fg 作业号 让停止的进程继续在前台运行

bg 作业号 让停止的进程继续在后台运行
kill -18 pid 让停止的进程继续在后台运行

二、进程的创建
(一)原理
进程的创建是通过 完全 拷贝父进程来实现的,子进程所有资源都来自于父进程。
子进程创建成功后,父子进程的执行相互独立
(二)fork函数–创建进程
1. 定义
#include <sys/types.h>
#include <unistd.h>pid_t fork(void);功能:拷贝父进程,产生子进程参数:无返回值:成功 给父进程返回子进程的PID 给子进程返回 0失败 -1 不会创建子进程 会重置错误码
2. 不关注返回值
在不考虑返回值时,调用n次fork函数,会产生2^n个进程(包含父进程)
#include <my_head.h>int main(int argc, char const *argv[])
{for(int i=0;i<2;i++){fork();printf("#"); }return 0;
}
输出结果:

分析结果:
要注意此处printf中并没有\n,即打印的’#‘存放在输出缓冲区中,而在循环第二次执行时,fork函数通过拷贝父进程生成子进程,即将其缓冲区也进行了拷贝,因此打印出了8个’#’
#include <my_head.h>int main(int argc, char const *argv[])
{for(int i=0;i<2;i++){fork();printf("#\n");}return 0;
}
输出结果:

分析结果:
要注意此处printf中有\n,此时的’#‘直接打印到了终端上,而在循环第二次执行时,fork函数通过拷贝父进程生成子进程,其缓冲区内是空的,直接又各自执行了一次打印操作,因此打印出了6个’#’
3. 关注返回值
fork函数给父进程返回子进程的pid,给子进程返回0,因此通过pid进行条件判断。
pid>0,说明当前进程是父进程;pid==0,说明当前进程是子进程,由此来使其执行各自的程序。
#include <my_head.h>int main(int argc, char const *argv[])
{printf("-----start-----\n");pid_t pid=fork();if(-1 == pid){ERR_LOG("fork error");}else if(0 < pid){printf("这是父进程\n");}else if(0 == pid){printf("这是子进程\n");}printf("-----end-----\n");return 0;
}

(三) 父子进程的执行顺序
父子进程执行,没有先后顺序,也是时间片轮转,谁得到cpu谁执行
(四)父子进程内存空间
父进程在fork产生子进程时,用到了写时拷贝的原则
如果父子进程中如果都只对同一个变量有读操作,那么不会重新映射到不同的物理内存;
只有在父子进程的中的任意一方执行了写操作时,才会重新映射到不同的物理内存

(五)使用实例
功能需求:使用父子进程拷贝文件,提高拷贝效率
因为cpu在执行程序时是按照时间片轮转的方式,哪个进程得到cpu就在这个时间片执行程序,而使用父子进程同时拷贝,就相当于增加了时间片轮转轮到的概率,由此提高拷贝效率。
需求分析:
fork之前打开的文件,fork之后,父子访问文件时是共用光标的。
如果不想让光标共用,可以在fork之后,父子进程中分别使用open去打开文件。
将源文件和目标文件一分为二,父进程复制文件开头到中间的位置的内容,子进程复制文件中间位置到结尾的内容,两个进程分别打开文件,不共用文件标识符
- 补充:关于可否使用父子进程在打开的文件中共用光标来实现拷贝的可实现性:
不能保证在一个时间片段内可以完整的执行完一条机器指令;因此可能会出现以下情况,如父进程读取了一段内容后,准备执行光标后移,但是未完成光标后移时就发生了时间片轮转,接着子进程再次复制时,光标并未移动,而重复读取内容。
代码实现:
#include <my_head.h>int main(int argc, char const *argv[])
{if(3 != argc){printf("Usage:%s src dest\n",argv[0]);exit(-1);}//获取文件大小struct stat file_stat;if(-1 == stat(argv[1],&file_stat))ERR_LOG("stat error");int size = file_stat.st_size;char buff[10]={0};int nbyte=0;int w_byte=0;//创建子进程pid_t pid=fork();if(-1==pid){ERR_LOG("fork error");}else if(0 < pid){//父进程//打开文件,从文件开头int src_fd = open(argv[1],O_RDONLY);int dest_fd = open(argv[2],O_WRONLY|O_CREAT,0666);//复制while(0 < (nbyte = read(src_fd,buff,sizeof(buff)))){write(dest_fd,buff,nbyte);//判断是不是写了一半w_byte=w_byte+nbyte;if(w_byte >= size/2) break;}//关闭文件close(src_fd);close(dest_fd);sleep(1);//等待子进程结束}else if(0 == pid){//子进程//打开文件,从文件中间int src_fd = open(argv[1],O_RDONLY);lseek(src_fd,size/2,SEEK_SET);int dest_fd = open(argv[2],O_WRONLY|O_CREAT,0666);lseek(dest_fd,size/2,SEEK_SET);//复制while(0 < (nbyte = read(src_fd,buff,sizeof(buff)))){write(dest_fd,buff,nbyte);}//关闭文件close(src_fd);close(dest_fd);}return 0;
}
三、 getpid/getppid
#include <sys/types.h>
#include <unistd.h>pid_t getpid(void);功能:返回调用进程的pid
参数:无
返回值:总是会成功pid_t getppid(void);功能:返回调用进程的父进程pid
参数:无
返回值:总是会成功
eg:使用fork创建进程,A创建B,B创建C,在每个进程中打印pid和ppid。
#include <my_head.h>int main(int argc, const char *argv[])
{pid_t pid = fork();if(-1 == pid){ERR_LOG("fork error");}else if(0 < pid){sleep(3);printf("我是A pid = [%d] ppid = [%d]\n", getpid(), getppid());}else if(0 == pid){if(-1 == (pid = fork())){ERR_LOG("fork error");}else if(0 < pid){sleep(1);printf("我是B pid = [%d] ppid = [%d]\n", getpid(), getppid());}else if(0 == pid){printf("我是C pid = [%d] ppid = [%d]\n", getpid(), getppid());}}return 0;
}
四、孤儿进程
子进程还没有执行完,父进程就结束了,此时子进程就是孤儿进程
孤儿进程会被 init 进程收养,当孤儿进程结束时 init 给他回收资源
孤儿进程就是一个正常的进程,当只不过其父进程变成了init。
他并不是进程状态的一种。
五、僵尸进程
当子进程运行结束后,父进程没有为其回收资源,此时子进程就是僵尸进程
僵尸进程对系统有害,占着资源不释放
三、进程退出exit/_exit函数
(一)exit
- 注:
- return 本身不使用来结束进程的,而是用来结束函数调用的,
- 只有在main函数中执行到return 才会结束整个进程 而在子函数中实行return只会结束函数调用
#include <stdlib.h>void exit(int status);功能:他是一个库函数,用来结束进程,他会刷新缓冲区参数:status:给父进程返回的进程退出状态值#define EXIT_FAILURE 1#define EXIT_SUCCESS 0返回值:无
(二)_exit
#include <unistd.h>void _exit(int status);功能:他是一个系统调用,用来结束进程,他不会刷新缓冲区参数:status:给父进程返回的进程退出状态值返回值:无
四、进程回收资源
(一)wait
#include <sys/types.h>
#include <sys/wait.h>pid_t wait(int *wstatus);功能:wait用于父进程中,用来阻塞等待任意一个子进程退出,给子进程回收资源子进程exit退出时的状态值 会被wait接收到。参数:wstatus:用来保存子进程退出状态的缓冲区的首地址如果不关心子进程退出的状态 可以传 NULL如果使用了:0-6:7个bit位中保存的是终止子进程的信号的编号8-15: 8个bit位保存的是子进程退出的状态值WIFEXITED(wstatus) 如果为真 说明子进程是正常结束的WEXITSTATUS(wstatus) 如果子进程是正常结束的 可以用它获取子进程退出的状态值WIFSIGNALED(wstatus) 如果为真 说明子进程是被信号中断的WTERMSIG(wstatus) 如果子进程是被信号中断的 可以使用它来获取终止子进程的信号的编号返回值:成功 终止的子进程的pid失败 -1 重置错误码
(二)waitpid
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *wstatus, int options);
功能:等待指定pid的子进程退出,为其回收资源
参数:pid:要回收资源的子进程的pid>0 回收指定pid的子进程的资源-1 回收任意一个子进程的资源0 回收和父进程同组的任意一个子进程的资源<-1 回收任意一个进程组id等于 pid 的绝对值的子进程的资源wstatus:和wait用法一样options:标志位 0 阻塞 WNOHANG 非阻塞
返回值:成功 回收资源的子进程的pid如果设置了 WNOHANG 且没有子进程退出时 返回 0失败 -1 重置错误码
注:
有下面等价的用法:
wait(NULL) <==> waitpid(-1, NULL, 0);
wait(&wstatus) <==> waitpid(-1, &wstatus, 0);
相关文章:
IO进程线程(六)进程
文章目录 一、进程状态(二)进程状态切换实例1. 实例1 二、进程的创建(一)原理(二)fork函数--创建进程1. 定义2. 不关注返回值3. 关注返回值 (三) 父子进程的执行顺序(四&…...
机器视觉——找到物块中心点
首先先介绍一下我用的是HALCON中的HDevelop软件。 大家下载好软件后可以测试一下: 在程序编辑器窗口中输入下面指令: read_image(Image,monkey) 那么如果出现这样的图片,说明是没有问题的 那么本次编程采用的是下面这张图片 我们要达到的…...
重磅消息! Stable Diffusion 3将于6月12日开源 2B 版本的模型,文中附候补注册链接。
在OpenAI发布Sora后,Stability AI也发布了其最新的模型Stabled Diffusion3, 之前的文章中已经和大家介绍过,感兴趣的小伙伴可以点击以下链接阅读。Sora是音视频方向,Stabled Diffusion3是图像生成方向,那么两者没有必然的联系&…...
Python报错:AttributeError: <unknown>.DeliveryStore 获取Outlook邮箱时报错
目录 报错提示: 现象描述 代码解释: 原因分析: 报错提示: in get_outlook_email return account.DeliveryStore.DisplayName line 106, in <module> email_address get_outlook_email() 现象描述 获取outlook本地邮箱…...
如何 Logrus IT 的质量评估门户帮助提升在线商店前端(案例研究)
在当今竞争激烈的电子商务环境中,一个运作良好的在线店面对商业成功至关重要。然而,确保目标受众获得积极的用户体验可能是一项挑战,尤其是在使用多种语言和平台时。Logrus IT的质量评估门户是一个强大的工具,可帮助企业简化内容和…...
程序调试
自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在程序开发过程中,免不了会出现一些错误,有语法方面的,也有逻辑方面的。对于语法方面的比较好检测,因…...
深度学习-07-反向传播的自动化
深度学习-07-反向传播的自动化 本文是《深度学习入门2-自製框架》 的学习笔记,记录自己学习心得,以及对重点知识的理解。如果内容对你有帮助,请支持正版,去购买正版书籍,支持正版书籍不仅是尊重作者的辛勤劳动…...
四川景源畅信:抖音做直播有哪些人气品类?
随着互联网科技的飞速发展,抖音作为新兴的社交媒体平台,已经成为了人们日常生活中不可或缺的一部分。而在抖音平台上,直播功能更是吸引了大量的用户和观众。那么,在抖音上做直播有哪些人气品类呢?接下来,就让我们一起…...
闲鱼无货源-高级班,最全·最新·最干,紧贴热点 深度学习(17节课)
课程目录 1-1:闲鱼潜规则_1.mp4 2-2:闲鱼的基础操作-养号篇_1.mp4 3-3:闲鱼实战运营-选品篇(一)_1.mp4 4-4:闲鱼实战运营-选图视频篇_1.mp4 5-5:闲鱼实战运营-标题筒_1.mp4 6-6࿱…...
力扣 739. 每日温度
题目来源:https://leetcode.cn/problems/daily-temperatures/description/ C题解:使用单调栈。栈里存放元素的索引,只要拿到索引就可以找到元素。 class Solution { public:vector<int> dailyTemperatures(vector<int>& tem…...
工业网关有效解决企业在数据采集、传输和整合方面的痛点问题-天拓四方
一、企业背景概述 随着信息技术的飞速发展,工业互联网已成为推动制造业转型升级的关键力量。在众多工业企业中,某公司凭借其深厚的技术积淀和广阔的市场布局,成为行业内的佼佼者。然而,在数字化转型的道路上,该公司也…...
金融壹账通的“新机遇” 用科技赋能助力金融机构做大做强“五篇大文章
金融强国、做好金融“五篇大文章”、发展新质生产力,正成为引导国内金融行业高质量发展的重要方向。 今年以来,越来越多银行保险机构为了做好金融“五篇大文章”,一面通过自主研发新科技,满足业务数字化需求,一面则积…...
Day 42 LVS四层负载均衡
一:负载均衡简介 1.集群是什么 集群(cluster)技术是一种较新的技术,通过集群技术,可以在付出较低成本的情况下获得在性能、可靠性、灵活性方面的相对较高的收益,其任务调度则是集群系统中的核心技术 …...
【源码】源码物品销售系统多种支付接口出售源码轻松赚钱
源码物品销售系统,多种支付接口,出售源码轻松赚钱。一款基于phpmysql开发的内容付费管理系统。系统支持多种收费方式,免签收款,三级分销,实名认证, 用户投稿/奖励,自动升级,佣金提现…...
图像操作的基石Numpy
OpenCV中用到的矩阵都要转换成Numpy数组 Numpy是一个经高度优化的Python数值库 创建矩阵 检索与赋值[y,x] 获取子数组[:,:] 一 创建数组array() anp.array([2,3,4]) cnp.array([1.0,2.0],[3.0,4.0]]) import numpy as npanp.array([1,2,3])bnp.array([[1,2,3],[4,5,6]])pr…...
如何利用exceljs将data数据导出表格实现日期去重,同时保留对应日期的每一列数据
const data [{ deviceId: 1, name: "B相电压", signalTypeId: 1, ts: "2024-05-13 12:10:06", unit: "kV", 1: 39.37936, value:39.37936, },{ deviceId: 1, name: "A相电压", signalTypeId: 2, ts: "2024-05-13 12:11:06"…...
[C#]使用C#部署yolov8-seg的实例分割的tensorrt模型
【测试通过环境】 win10 x64 vs2019 cuda11.7cudnn8.8.0 TensorRT-8.6.1.6 opencvsharp4.9.0 .NET Framework4.7.2 NVIDIA GeForce RTX 2070 Super 版本和上述环境版本不一样的需要重新编译TensorRtExtern.dll,TensorRtExtern源码地址:TensorRT-CShar…...
写个删除obj文件夹、bin文件夹的小工具
每次编译代码成功后都会生成obj/bin等文件夹。因此想清理这些文件夹,无奈工程数量较多,每个都要手动去删除比较累。就想到用代码写个小工具删除,当然也可以利用bat批处理删除。 using System; using System.Collections.Generic; using Syst…...
【多目标跟踪】《FlowMOT: 3D Multi-Object Tracking by Scene Flow Association》论文阅读笔记
0.论文 论文地址链接:https://arxiv.org/pdf/2012.07541v1 通过流的方式跟踪是一个比较新颖的点,所以这里比较关注运动跟踪,是如果做到流的跟踪来预测目标的位置以及ID绑定的。 FlowMOT的框架结构如下所示,本中会主要关注下运动跟踪、数据关联、ID分配、新生/消亡…...
python长方形周长面积 2024年3月青少年编程电子学会python编程等级考试二级真题解析
目录 python长方形周长面积 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python长方形周长面积 2024年3月 python编程等级考试级编程题 一、…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
