# issue 4 进程控制函数

news2024/12/23 17:29:20

目录

一、进程控制函数一

二、进程控制函数二

启动进程:(exec系列)

创建新进程:

测试代码:

测试结果:

三、进程控制函数三

结束进程:

测试代码:

测试结果:

四、进程控制函数四

改变进程的流程:(相同颜色请配套食用)

测试代码:

测试结果:

五、进程控制函数五

获取进程状态(组id,组识别码,进程id)

测试代码:

测试结果:

六、进程控制函数六

设置进程状态

测试代码:

测试结果:

七:进程控制函数七


一、进程控制函数一

什么是进程?

进程是操作系统调度的最小单位。注意:线程并不是由操作系统调度的,而是由进程自己调度。

进程有多种状态:运行、休眠、结束、暂停、挂起等,进程下的线程也会是相应的状态。

二、进程控制函数二

启动进程:(exec系列)

<unistd.h>
int execl(const char *path, const char *arg, ...)
int execlp(const char *file, const char *arg, ...)
int execle(const char *path, const char *arg, ..., char * const envp[])
int execv(const char *path, char *const argv[])
int execvp(const char *file, char *const argv[])
int execve(const char * filename,char * const argv[ ],char * const envp[ ])内核级别调用

其中:

l :进程执行的参数,以可变参数的形式给出的,这些参数必须以NULL 为最后一个参数

p :exec(进程函数)会将当前的PATH 作为一个参考环境变量。这意味着你填路径时可以不用填绝对路径,可以填相对路径(const char *path

e :进程函数需要用户来设置这个环境变量(char * const envp[]

v :进程函数会用参数数组来传递argv,数组的最后一个成员必须是NULL(char *const argv[]

这里注意:区别于fork,因为exec系列并不是真正的创建一个,而是用一个用户指定的命令把本进程替换掉。

创建新进程:

pid_t fork( void)

返回值:
大于0 的数,此时就是父进程
等于0 的数,此时就是子进程
小于0 的数,表示调用失败
注意:进程数量是有限的1~32768/32767/65535

测试代码:

void lession32() {
	pid_t pid = fork();
	if (pid > 0) {//父进程
		//sleep(1);
		std::cout << "hello,here is parent!\n" << pid << std::endl;
	}
	else {//子进程
		sleep(3);
		execl("/usr/bin/ls", "ls", "-l", NULL);//argv的第一个参数一定要是命令自身
	}
}

测试结果:

我们可以发现:fork()这个函数有点牛逼,会返回两次,先是父进程再是子进程

注意: 谁是你的父进程谁就调用fork  ;fork会返回两次

三、进程控制函数三

结束进程:

以异常方式结束进程:     (并不会触发析构等一系列操作)
void abort(void)
若测试的条件不成立则终止进程:   (断言的方式终止)(当参数为0时终止进程)

#include <assert.h>
void assert(int expression)


正常结束进程:   (可以触发进程结束的调用函数)
void exit(int status)
结束进程执行:   (不可以触发)
void _exit(int status)


设置程序正常结束前调用的函数:
int atexit(void (*func)(void))
设置程序正常结束前调用的函数:
int on_exit(void (* function)(int,void*),void *arg)

测试代码:

#include <assert.h>//断言
void lession33_exit() {
	printf("%s\n", __FUNCTION__);//打印S函数名称
}
void lession33_on_exit(int status,void*p) {
	printf("%s p=%p status=%d \n", __FUNCTION__,p, status);
}
void lession33() {
	pid_t pid = fork();
	if (pid > 0) {
		std::cout << "hello,here is parent!\npid=" << pid << std::endl;
		//abort();
		atexit(lession33_exit);//进程结束时时调用
		exit(0);
	}
	else {//子进程
		
		sleep(3);
		assert(0);//触发断言
		on_exit(lession33_on_exit, (void*)1);//子进程结束时时调用
		_exit(-1);//不会触发on_exit 的调用
		std::cout << "here is son!\r\n";
	}
}

测试结果:

四、进程控制函数四

改变进程的流程:(相同颜色请配套食用)

保存目前堆栈环境:

#include <setjmp.h>
int setjmp(jmp_buf environment)
注意:jmp_buf 存储的是寄存器信息(当跳转的时候进行恢复)(补充解释:cpu,无论是arm还是x86架构,大部分cpu的状态存储在寄存器里面。setjmp会把所有buf保存 ,其中的一个buf:IP(指令指针寄存器),在arm叫PC,x86叫IP。所以不同架构下,数据结构不一样。PC:R0,R16     IP:eax,ebx。IP中存储着CPU要执行的指令的值(地址)。)
保存目前堆栈环境:
int sigsetjmp(sigjmp_buf env, int savemask)

这个不仅缓存寄存器,还会缓存上下文
上下文:堆栈、当前寄存器、当前的状态(线程,进程)、下一条指令的位置、栈内存地址

需要再配套struct sigaction食用。具体用法见测试代码


跳转到原先setjmp 保存的堆栈环境:
void longjmp(jmp_buf environment, int value)
改变进程优先顺序:跳转到原先sigsetjmp 保存的堆栈环境
void siglongjmp(sigjmp_buf env, int val)

测试代码实现了一个简单的异常捕获。深入的用法是在逆向中,先setjmp,然后故意触发一些东西,例如崩溃,然后切到中断处理的函数里,进行一些骚操作,然后再恢复。变相实现修改。

测试代码:

#include <setjmp.h>
#include<signal.h>
jmp_buf jmpbuf;   //建议设置成全局变量or静态的,不建议设置成局部的,因为后面longjmp会调用,会跨函数
void test003() {
	//TODO
	longjmp(jmpbuf, 2);
}
void test002() {
	//模拟在test002中发生异常
	longjmp(jmpbuf, 1);    //直接跳转
}
void test001() {
	//TODO
	test002();
}
void signal_deal(int signo) {
	if (signo == SIGSEGV)
		longjmp(jmpbuf, SIGSEGV);
}
void lession34() {
	signal(SIGSEGV/*断错误(如访问了不该访问的内存)*/, signal_deal);   //异常捕获   配合食用
 	struct sigaction act,actold;
	//act.sa_handler = signal_deal;
	sigaction(SIGSEGV, &act, &actold);

	int ret = setjmp(jmpbuf);    //这里setjmp把所有寄存器全部保存了,包括IP寄存器
	if ( ret== 0) {  //这实际上是,C中处理异常的一种机制
		test001();
		*(int*)(NULL) = 0;
	}
	else if (ret == 1) {//错误1的处理和恢复
		std::cout << "error 1\n";
	}
	else if (ret == 2) {//错误2的处理和恢复
		std::cout << "error 2\n";
	}
	else if (ret == SIGSEGV) {//断错误的处理和恢复
		std::cout << "error SIGSEGV\n";
	}
}

测试结果:

五、进程控制函数五

获取进程状态(组id,组识别码,进程id)

pid_t getpgid(pid_t pid)           //取得进程组识别码
pid_t getpgrp(void)                //取得当前进程组识别码
pid_t getpid(void)                 //取得进程识别码
pid_t getppid(void)                //取得父进程的进程识别码   谁派生的我
int getpriority(int which,int who) //取得程序进程执行优先权   优先级可以是负数,越小越牛逼 
                                                     //对于-20的进程,系统优先响应 对于20的进程,系统会先挂起

注意:进程的进程id是进程的唯一标识,进程id是唯一的(取值范围:0-32768 or 65535)

注意:同一个进程,同一时间内,只能被一个进程调试。所以可以通过一个父进程派生一个子进程调试,然后go掉父进程,这样就可以实现反调试。

默认情况下进程id就是组id

测试代码:

#include <sys/resource.h>
void lession35() {
	std::cout << "getpgid某进程组id:" << getpgid(getpid()) << std::endl;
	std::cout << "getpgrp当前进程组id:" << getpgrp() << std::endl;
	std::cout << "getpid当前进程id:" << getpid() << std::endl;
	std::cout << "getppid当前进程的父id:" << getppid() << std::endl;
	std::cout << "getpriorit当前进程优先级" << getpriority(PRIO_PROCESS,getpid()) << std::endl;
	sleep(15);
}

测试结果:

 

六、进程控制函数六

设置进程状态

注意:必须要有足够的权限(启动的有效用户必须要有足够的权限)

int setpgid(pid_t pid,pid_t pgid)            //设置进程组识别码
int setpgrp(void)                            //设置进程组识别码  把组id设置成进程id  如果设置失败返回-1
int setpriority(int which,int who, int prio) //设置程序进程执行优先权 超出用户权限的没法完成  如果设置失败返回-1
int nice(int inc)                            //改变进程优先级 超出用户权限的没法完成

注意:无法修改进程的id,因为进程id是唯一的标识,即便root也不可以

测试代码:

void lession36() {
	std::cout << "--getpgrp当前进程组id:" << getpgrp() << std::endl;
	std::cout<<"setpgid:"<<setpgid(getpid(),1)<<std::endl;
	std::cout << "--getpgrp当前进程组id:" << getpgrp() << std::endl;
	std::cout<<"setpgrp:"<<setpgrp()<<std::endl;
	std::cout << "--getpgrp当前进程组id:" << getpgrp() << std::endl;
	std::cout << "--getpriorit:" << getpriority(PRIO_PROCESS, getpid()) << std::endl;
	std::cout << "改变优先级nice:" << nice(3)<< std::endl;
	std::cout << "--getpriorit:" << getpriority(PRIO_PROCESS, getpid()) << std::endl;
	std::cout << "设置优先级setpriorit:" << setpriority(PRIO_PROCESS, getpid(), -1) << std::endl;
	std::cout << "--getpriorit:" << getpriority(PRIO_PROCESS, getpid()) << std::endl;
}

测试结果:

七:进程控制函数七

<stdlib.h>
int system(char *command)
//执行shell 命令
//例如ls -l;
//可以通过这个来进行组合命令,达到类似于批处理的功能

<sys/types.h>
<sys/wait.h>
int wait(int *status)
//等待一个状态(子进程的状态) 一般来讲是和fork 配套使用
//当子进程结束的时候会得到一个返回值  并且状态值会被设置,如果status是空指针那么状态值会被丢弃,如果是有效的地址,那么状态值会设置到地址中
//流程上:先调用fork,再调用wait(父进程调用)   fork 开辟一个子进程 在开辟过程中会有一个SIGCHILD的量,意思如果开辟成功则会发送一个信号量过来。那么wait就会等待子进程结束
//因为当子进程销毁时,会向父进程报告(发送SIGCHILD)。如果父进程没有接收到这个报告,则子进程可能被阻塞成为僵尸进程(会占用进程id--pid,会消耗系统资源)
pid_t waitpid(pid_t pid,int * status,int options)//等待指定子进程的中断或结束

options:
WNOHANG //非阻塞,非挂起
WUNTRACED //被调试,主要用于反调试
WCONTINUED //发生了信号导致进程暂停  例如:SIGSTOP(进程停止) SIGPAUSE(进程暂停) SIGCONT(恢复) 注意后两个状态自己不可处理,由系统处理

status:
WIFEXITED(status)   //是否退出,一个宏,返回1表示退出,0表示正在运行
WEXITSTATUS(status)  //获取status的具体值

WIFSIGNALED(status)     //是否有信号量过来导致暂停
WTERMSIG(status)        //拿到信号量,是什么一个信号量导致暂停

WIFSTOPPED(status)       //导致停止
WSTOPSIG(status)         //拿到信号,什么信号量导致停止

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

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

相关文章

Linux|进程程序替换

目录 什么是进程替换 替换原理 exec函数 exec* 函数的共性 什么是进程替换 进程程序替换是指将一个进程中正在运行的程序替换为另一个全新的程序的过程&#xff0c;但替换不是创建新进程&#xff0c;只是将对应程序的代码和数据进行替换。具体来说&#xff0c;这个替换过程涉…

2024 APMCM亚太数学建模C题 - 宠物行业及相关产业的发展分析和策略(详细解题思路)

在当下&#xff0c; 日益发展的时代&#xff0c;宠物的数量应该均为稳步上升&#xff0c;在美国出现了下降的趋势&#xff0c; 中国 2019-2020 年也下降&#xff0c;这部分变化可能与疫情相关。需要对该部分进行必要的解释说明。 问题 1: 基于附件 1 中的数据及您的团队收集的…

人工智能(AI)与机器学习(ML)基础知识

目录 1. 人工智能与机器学习的核心概念 什么是人工智能&#xff08;AI&#xff09;&#xff1f; 什么是机器学习&#xff08;ML&#xff09;&#xff1f; 什么是深度学习&#xff08;DL&#xff09;&#xff1f; 2. 机器学习的三大类型 &#xff08;1&#xff09;监督式学…

【从零开始的LeetCode-算法】3233. 统计不是特殊数字的数字数量

给你两个 正整数 l 和 r。对于任何数字 x&#xff0c;x 的所有正因数&#xff08;除了 x 本身&#xff09;被称为 x 的 真因数。 如果一个数字恰好仅有两个 真因数&#xff0c;则称该数字为 特殊数字。例如&#xff1a; 数字 4 是 特殊数字&#xff0c;因为它的真因数为 1 和…

web——sqliabs靶场——第十二关——(基于错误的双引号 POST 型字符型变形的注入)

判断注入类型 a OR 1 1# 发现没有报错 &#xff0c;说明单引号不是闭合类型 测试别的注入条件 a) OR 1 1# a)) OR 1 1# a" OR 11 发现可以用双引号闭合 发现是")闭合 之后的流程还是与11关一样 爆破显示位 先抓包 是post传参&#xff0c;用hackbar来传参 unam…

IDEA 下载源码很慢,Download Source使用阿里云镜像仓库

参考&#xff1a; IDEA maven本地仓库、中心仓库、远程仓库配置 在观看第三方jar包的api时&#xff0c;有时候需要下载源码看下注释。 这个时候用idea 上的提示的Download Source会发现一直下载不下来。 因此就怀疑用的是apache的maven仓库&#xff0c;不是我们用的 aliyun 镜…

1+X应急响应(网络)病毒与木马的处置:

病毒与木马的处置&#xff1a; 病毒与木马的简介&#xff1a; 病毒和木马的排查与恢复&#xff1a;

2024年亚太地区数学建模大赛D题-探索量子加速人工智能的前沿领域

量子计算在解决复杂问题和处理大规模数据集方面具有巨大的潜力&#xff0c;远远超过了经典计算机的能力。当与人工智能&#xff08;AI&#xff09;集成时&#xff0c;量子计算可以带来革命性的突破。它的并行处理能力能够在更短的时间内解决更复杂的问题&#xff0c;这对优化和…

一个小的可编辑表格问题引起的思考

11.21工作中遇到的问题 预期&#xff1a;当每行获取红包金额的时候若出现错误&#xff0c;右侧当行会出现提示 结果&#xff1a;获取红包金额出现错误&#xff0c;右侧对应行并没有出现错误提示 我发现&#xff0c;当我们设置readonly的时候&#xff0c;其实render函数依旧是…

【Linux课程学习】:进程描述---PCB(Process Control Block)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux课程学习 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 1.基本概念&#xff1a; &#x1f95d;进程的…

java基础概念36:正则表达式1

一、正则表达式的作用 作用一&#xff1a;校验字符串是否满足规则&#xff1b;作用二&#xff1a;在一段文本中查找满足要求的内容。——爬虫 二、正则表达式 2-1、字符类 示例&#xff1a; public static void main(String[] args) {System.out.println("a".matc…

设计模式之 命令模式

命令模式&#xff08;Command Pattern&#xff09;是行为型设计模式之一&#xff0c;它将请求&#xff08;或命令&#xff09;封装成一个对象&#xff0c;从而使用户能够将请求发送者与请求接收者解耦。通过命令模式&#xff0c;调用操作的对象与执行操作的对象不直接关联&…

GRU (门控循环单元 - 基于RNN - 简化LSTM又快又好 - 体现注意力的思想) + 代码实现 —— 笔记3.5《动手学深度学习》

目录 0. 前言 1. 门控隐状态 1.1 重置门和更新门 1.2 候选隐状态 1.3 隐状态 2. 从零开始实现 2.1 初始化模型参数 2.2 定义模型 2.3 训练与预测 3 简洁实现 4. 小结 0. 前言 课程全部代码&#xff08;pytorch版&#xff09;已上传到附件看懂上一篇RNN的所有细节&am…

实践篇:青果IP助理跨境电商的高效采集

写在前面&#xff1a; 近年来&#xff0c;跨境电商行业迅速崛起&#xff0c;成为全球贸易的重要组成部分。据市场调研机构Statista数据显示&#xff0c;2024年全球跨境电商市场规模预计将突破5万亿美元&#xff0c;覆盖数十亿消费者。跨境电商的竞争日益激烈&#xff0c;商家不…

电子应用设计方案-16:智能闹钟系统方案设计

智能闹钟系统方案设计 一、系统概述 本智能闹钟系统旨在为用户提供更加个性化、智能化和便捷的闹钟服务&#xff0c;帮助用户更有效地管理时间和起床。 二、系统组成 1. 微控制器 - 选用低功耗、高性能的微控制器&#xff0c;如 STM32 系列&#xff0c;负责整个系统的控制和数据…

QML —— 3种等待指示控件(附源码)

效果如下 说明 BusyIndicator应用于指示在加载内容或UI被阻止等待资源可用时的活动。BusyIndicator类似于一个不确定的ProgressBar。两者都可以用来指示背景活动。主要区别在于视觉效果,ProgressBar还可以显示具体的进度(当可以确定时)。由于视觉差异,繁忙指示器和不确定的…

Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)

链接 链接2 这两道题略微有点难&#xff0c;其中第一道题我自己解出来了&#xff0c;还补充了一个更好的解法&#xff0c;在空间上做了优化。 第二道题看了别人的题解&#xff0c;我正在努力理解。 题目一&#xff1a; 题意&#xff1a;为什么有n个元素&#xff0c;但是还有…

通过轻易云平台实现聚水潭数据高效集成到MySQL的技术方案

聚水潭数据集成到MySQL的技术案例分享 在本次技术案例中&#xff0c;我们将详细探讨如何通过轻易云数据集成平台&#xff0c;将聚水潭的数据高效、可靠地集成到MySQL数据库中。具体方案为“聚水谭-店铺查询单-->BI斯莱蒙-店铺表”。这一过程不仅需要处理大量数据的快速写入…

华为云容器监控平台

首先搜索CCE,点击云容器引擎CCE 有不同的测试&#xff0c;生产&#xff0c;正式环境 工作负载--直接查询服务名看监控 数据库都是走的一个 Redis的查看

机器学习系列----关联分析

目录 1. 关联分析的基本概念 1.1定义 1.2常用算法 2.Apriori 算法的实现 2.1 工作原理 2.2 算法步骤 2.3 优缺点 2.4 时间复杂度 2.5实际运用----市场购物篮分析 3. FP-Growth 算法 3.1 工作原理 3.2 算法步骤 3.3 优缺点 3.4 时间复杂度 3.5实际运用——网页点…