当前位置: 首页 > news >正文

(Linux 系统)进程控制

目录

一、进程创建

1、fork函数初识

二、进程终止

1、正常终止

2、异常终止

三、进程等待

1、进程等待必要性

2、进程等待的方法:

四、获取子进程status

1、基本概念

2、进程的阻塞等待方式

3、进程的非阻塞等待方式

五、进程程序替换

1、六种替换函数

2、可执行程序和脚本能跨语言调用的原因

3、环境变量是什么时候给进程的


一、进程创建

1、fork函数初识

在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。

#include<unistd.h>

pid_t fork(void);

返回值:自进程中返回0,父进程返回子进程id,出错返回-1

二、进程终止

代码运行完毕,结果正确

代码运行完毕,结果不正确

代码异常终止

1、正常终止

可以通过 echo  $? 查看进程退出码

1. 从main返回

2. 调用exit

3. _exit 异常退出:

_exit与exit区别:

_exit为纯正的系统调用,

exit最后也会调用_exit, 但在调用 _exit之前,还做了其他工作: 1. 执行用户通过 atexit或on_exit定义的清理函数。 2. 关闭所有打开的流,所有的缓存数据均被写入 3. 调用_exit

2、异常终止

ctrl + c,信号终止

异常时的退出码没有意义

三、进程等待

如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。 如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。 如果不存在该子进程,则立即出错返回。

1、进程等待必要性

子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。 进程一旦变成僵尸状态,就不能被杀死。 父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息。

2、进程等待的方法:

wait方法

阻塞等待

#include<sys/types.h>

#include pid_t wait(int*status);

返回值: 成功返回被等待进程pid,失败返回-1。

参数: 输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

②waitpid方法

pid_ t waitpid(pid_t pid, int *status, int options);

返回值: 当正常返回的时候waitpid返回收集到的子进程的进程ID; 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0; 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;

参数:

pid: Pid=-1,等待任一个子进程。与wait等效。 Pid>0.等待其进程ID与pid相等的子进程。

status: WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出) WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)

options: WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进 程的ID。

四、获取子进程status

1、基本概念

wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。 如果传递NULL,表示不关心子进程的退出状态信息。 否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。 status不能简单的当作整形来看待,可以当作位图来看待。

2、进程的阻塞等待方式

int main(){pid_t pid;pid = fork();if(pid < 0){printf("%s fork error\n",__FUNCTION__);return 1;} else if( pid == 0 ){ //childprintf("child is run, pid is : %d\n",getpid());sleep(5);exit(257);} else{int status = 0;pid_t ret = waitpid(-1, &status, 0);//阻塞式等待,等待5Sprintf("this is test for wait\n");if( WIFEXITED(status) && ret == pid ){printf("wait child 5s success, child return code is :%d.\n",WEXITSTATUS(status));}else{printf("wait child failed, return.\n");return 1;}}return 0;}

3、进程的非阻塞等待方式

#include <stdio.h>  
#include <unistd.h>#include <stdlib.h>#include <sys/wait.h>int main(){pid_t pid;pid = fork();if(pid < 0){printf("%s fork error\n",__FUNCTION__);return 1;}else if( pid == 0 ){ //childprintf("child is run, pid is : %d\n",getpid());sleep(5);exit(1);} else{int status = 0;pid_t ret = 0;do{ret = waitpid(-1, &status, WNOHANG);//非阻塞式等待if( ret == 0 ){printf("child is running\n");}sleep(1);}while(ret == 0);if( WIFEXITED(status) && ret == pid ){printf("wait child 5s success, child return code is :%d.\n",WEXITSTATUS(status));}else{printf("wait child failed, return.\n");return 1;}}return 0;}

五、进程程序替换

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数 以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动 例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。

1、六种替换函数

 #include <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[]);

程序替换成功后,exec*之后的代码不会被执行,替换失败了才可能会执行后续代码

exec系列函数只有失败返回值,没有成功返回值,承担加载器的效果

Linux中形成的可执行程序是有格式的,ELF,可执行程序的表头。

exec系列函数可以调用系统命令,也可以调用我们自己编译的可执行程序

2、可执行程序和脚本能跨语言调用的原因

所有语言写的代码运行起来本质都是进程

3、环境变量是什么时候给进程的

环境变量也是数据,创建子进程的时候,环境变量就已经被子进程继承下去。

http://www.lryc.cn/news/494168.html

相关文章:

  • 【Nativeshell】flutter的pc跨平台框架学习记录<二> 窗口间通信
  • 今日codeforces刷题(1)
  • 【C++算法】20.二分查找算法_x 的平方根
  • 图像显示的是矩阵的行和列,修改为坐标范围。
  • 通义灵码走进北京大学创新课堂丨阿里云云原生 10 月产品月报
  • LeetCode Hot100 1~10
  • npm 最新国内淘宝镜像地址源 (旧版已不能用)
  • DepthAI 2.29版本 发布
  • C#反序列化XML时提示XML 文档(1, 1)中有错误
  • C# 中的接口:定义行为契约与实现多态性
  • Redis的基础知识·
  • qt QProxyStyle详解
  • AWS CLI 操作指南
  • 海盗王用golang重写的AccountServer功能
  • 如何保证spring boot应用程序的安全性?
  • 力扣 岛屿数量-200
  • 极狐GitLab 17.6 正式发布几十项与 DevSecOps 相关的功能【三】
  • 十二、正则表达式、元字符、替换修饰符、手势和对话框插件、字符串截取
  • 【信息系统项目管理师】第3章:信息系统治理 考点梳理
  • 实现对图片或者视频增加隐藏水印和提取水印
  • uniapp配置全局消息提醒
  • 卸载snap docker一直卡住:Save data of snap “docker“ in automatic snapshot set #3
  • python学习——字典元素的访问和遍历
  • 数据结构基础之《(9)—归并排序》
  • 【深度学习】各种卷积—卷积、反卷积、空洞卷积、可分离卷积、分组卷积
  • 远程视频验证如何改变商业安全
  • 电脑启动需要经历哪些过程?
  • 纯Go语言开发人脸检测、瞳孔/眼睛定位与面部特征检测插件-助力GoFly快速开发框架
  • postman使用正则表达式提取数据实战篇!
  • ipmitool使用详解(三)-解决各种dell、hp服务器无法ipmitool连接问题