# issue 4 进程控制函数

目录

一、进程控制函数一

二、进程控制函数二

启动进程:(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() {//TODOlongjmp(jmpbuf, 2);
}
void test002() {//模拟在test002中发生异常longjmp(jmpbuf, 1);    //直接跳转
}
void test001() {//TODOtest002();
}
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.mzph.cn/news/887169.shtml

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

相关文章

Java项目实战II基于SpringBoot的共享单车管理系统开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在共享经济蓬勃发展的今天…

Linux 网络编程之UDP套接字

前言 前面我们对网络的发展&#xff0c;网络的协议、网路传输的流程做了介绍&#xff0c;最后&#xff0c;我们还介绍了 IP 和 端口号&#xff0c;ip port 叫做 套接字 socket&#xff0c; 本期我们就来介绍UDP套接字编程&#xff01; 目录 1、预备知识 1.1 传输层协议: T…

---Arrays类

一 java 1.Arrays类 1.1 toString&#xff08;&#xff09; 1.2 arrays.sort( )-----sort排序 1&#xff09;直接调用sort&#xff08;&#xff09; Arrays.sort() 方法的默认排序顺序是 从小到大&#xff08;升序&#xff09;。 2&#xff09;定制排序【具体使用时 调整正负…

Java 对象头、Mark Word、monitor与synchronized关联关系以及synchronized锁优化

1. 对象在内存中的布局分为三块区域&#xff1a; &#xff08;1&#xff09;对象头&#xff08;Mark Word、元数据指针和数组长度&#xff09; 对象头&#xff1a;在32位虚拟机中&#xff0c;1个机器码等于4字节&#xff0c;也就是32bit&#xff0c;在64位虚拟机中&#xff0…

6.7机器学习期末复习题

空间 样本空间 就是属性的所有可能情况&#xff0c;包括了一切可能出现或不可能出现的所有样本情况 版本空间&假设空间 假设空间就是在样本空间的基础上&#xff0c;给所有属性都加了一个通配符&#xff0c;表示任意即可&#xff1b;以及加上了一个空集&#xff0c;表示…

Qt界面设计时使各控件依据窗口缩放进行栅格布局的方法

图1 最终效果 想要达成上述图片的布局效果&#xff0c;具体操作如下&#xff1a; 新建一窗体&#xff1a; 所需控件如下&#xff1a; Table View控件一个&#xff1b; Group Box控件一个&#xff1b; Push Button控件2个&#xff1b; Horiziontal Spacer控件2个&#xf…

mac安装Pytest、Allure、brew

安装环境 安装pytest 命令 pip3 install pytest 安装allure 命令&#xff1a;brew install allure 好吧 那我们在安装allure之前 我们先安装brew 安装brew 去了官网复制了命令 还是无法下载 如果你们也和我一样可以用这个方法哦 使用国内的代码仓库来执行brew的安装脚本…

数据结构C语言描述5(图文结合)--队列,数组、链式、优先队列的实现

前言 这个专栏将会用纯C实现常用的数据结构和简单的算法&#xff1b;有C基础即可跟着学习&#xff0c;代码均可运行&#xff1b;准备考研的也可跟着写&#xff0c;个人感觉&#xff0c;如果时间充裕&#xff0c;手写一遍比看书、刷题管用很多&#xff0c;这也是本人采用纯C语言…

一篇文章了解机器学习

一篇文章了解机器学习&#xff08;上&#xff09; 一、软件版本安装二、数据集的加载三、数据集的切分四、数据特征提取及标准化1、字典数据的特征提取2、文本特征向量的提取3、数据标准化处理 四、特征降维注&#xff1a;训练器的区别&#xff1a;&#xff1a;五、模型的训练与…

day03(单片机高级)RTOS

目录 RTOS(实时操作系统) 裸机开发模式 轮询方式 前后台&#xff08;中断方式&#xff09; 改进&#xff08;前后台&#xff08;中断&#xff09;&#xff09;定时器 裸机进一步优化 裸机的其他问题 RTOS的概念 什么是RTOS 为什么要使用 RTOS RTOS的应用场景 RTOS的…

Hello-Go

Hello-Go 环境变量 GOPATH 和 GOROOT &#xff1a;不同于其他语言&#xff0c;go中没有项目的说法&#xff0c;只有包&#xff0c;其中有两个重要的路径&#xff0c;GOROOT 和 GOPATH Go开发相关的环境变量如下&#xff1a; GOROOT&#xff1a;GOROOT就是Go的安装目录&…

pytorch官方FasterRCNN代码详解

本博文转自捋一捋pytorch官方FasterRCNN代码 - 知乎 (zhihu.com)&#xff0c;增加了其中代码的更详细的解读&#xff0c;以帮助自己理解该代码。 代码理解的参考Faster-RCNN全面解读(手把手带你分析代码实现)---前向传播部分_手把手faster rcnn-CSDN博客 1. 代码结构 作为 to…

全志T113双核异构处理器的使用基于Tina Linux5.0——RTOS系统定制开发

8、RTOS系统定制开发 此处以在rtos/components/aw目录下创建一个简单的软件包为例&#xff0c;帮助客户了解RTOS环境&#xff0c;为RTOS系统定制开发提供基础。 RTOS环境下的软件包主要由三部分组成&#xff0c;源文件&#xff0c;Makefile&#xff0c;Kconfig&#xff0c;如下…

springboot实战(13)(@PatchMapping、@RequestParam、@URL、ThreadLocal线程局部变量)

目录 一、PATCH请求方式。 二、实现用户更新头像功能。 三、注解RequestParam。 四、注解URL。&#xff08;对传来的参数是否是合法地址进行校验&#xff09; 一、PATCH请求方式。 patch中文翻译&#xff1a;局部、小块。PATCH 请求主要用于对已存在的资源进行局部修改&#xf…

nvm安装node遇到的若干问题(vscode找不到npm文件、环境变量配置混乱、npm安装包到D盘)

问题一&#xff1a;安装完nvm后需要做哪些环境变量的配置&#xff1f; 1.打开nvm文件夹下的setting文件&#xff0c;设置nvm路径和安装node路径&#xff0c;并添加镜像。 root: D:\software\nvm-node\nvm path: D:\software\nvm-node\nodejs node_mirror: https://npmmirror.c…

面向FWA市场!移远通信高性能5G-A模组RG650V-NA通过北美两大重要运营商认证

近日&#xff0c;全球领先的物联网整体解决方案供应商移远通信宣布&#xff0c;其旗下符合3GPP R17标准的新一代5G-A模组RG650V-NA成功通过了北美两家重要运营商认证。凭借高速度、大容量、低延迟、高可靠等优势&#xff0c;该模组可满足CPE、家庭/企业网关、移动热点、高清视频…

2024年11月21日Github流行趋势

项目名称&#xff1a;twenty 项目维护者&#xff1a;charlesBochet, lucasbordeau, Weiko, FelixMalfait, bosiraphael项目介绍&#xff1a;正在构建一个由社区支持的现代化Salesforce替代品。项目star数&#xff1a;21,798项目fork数&#xff1a;2,347 项目名称&#xff1a;p…

AWTK 最新动态:支持鸿蒙系统(HarmonyOS Next)

HarmonyOS是全球第三大移动操作系统&#xff0c;有巨大的市场潜力&#xff0c;在国产替代的背景下&#xff0c;机会多多&#xff0c;AWTK支持HarmonyOS&#xff0c;让AWTK开发者也能享受HarmonyOS生态的红利。 AWTK全称为Toolkit AnyWhere&#xff0c;是ZLG倾心打造的一套基于C…

docker 配置同宿主机共同网段的IP 同时通过通网段的另一个电脑实现远程连接docker

docker配置网络 #宿主机执行命令 ifconfig 查询对应的主机ip 子网掩码 网关地址 #[网卡名称]&#xff1a;inet[主机IP] netmask[子网掩码] broadcast[网关地址]这里需要重点关注&#xff1a;eno1[网卡名称]以及【192.168.31.225】网关地址 在宿主机执行docker命令创建一个虚拟…

使用 Elastic AI Assistant for Search 和 Azure OpenAI 实现从 0 到 60 的转变

作者&#xff1a;来自 Elastic Greg Crist Elasticsearch 推出了一项新功能&#xff1a;Elastic AI Assistant for Search。你可以将其视为 Elasticsearch 和 Kibana 开发人员的内置指南&#xff0c;旨在回答问题、引导你了解功能并让你的生活更轻松。在 Microsoft AI Services…