IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 【Linux】进程控制 -> 正文阅读

[系统运维]【Linux】进程控制

一、进程退出

main函数return0是为什么?

main函数返回的是进程的退出码

  • 输出最近一次进程的退出码
echo $?

image-20220409104720205


1. 进程退出场景

  • 代码运行完毕,结果正确
  • ——————,结果不正确
  • 代码异常终止(程序崩溃)

2. 查看每个退出码所传递的信息

strerror

  1 #include <iostream>
  2 #include <string.h>
  3 using namespace std;
  4 
  5 
  6 int main()
  7 {
  8   for(int i = 0; i < 10; i++)
  9   {
 10     cout << i << ":" << strerror(i) << endl;                                                                                                        
 11   }
 12   return 0;
 13 }
 14 
~

image-20220409110007432

可以看出最多是133

image-20220409110212537


3. 终止进程

exit,强制退出,参数是退出码

image-20220409111949231


二者效果相似,且会将保存在缓冲区的数据输出,缓冲区刷新

exit(EXIT_SUCCESS);
return 0;

_exit 终止进程,但不刷新缓冲区(以及后续的收尾工作)

image-20220409111128865


总结:进程退出三种方式:mian函数return0;exit;_exit;

进程退出,0S层面做了什么:
系统层面,少了一个进程: free PCB, free, mm_ struct, free 页表和各种映射关系,代码+数据申请的空间也要释放掉


二、进程等待

为什么要让父进程等待呢?

  • 通过获取子进程退出的信息,能够得知子进程执行结果。

  • 可以保证时序问题,子进程先退出。父进程后退出

  • 进程退出的时候会先进入僵尸状态,会造成内存泄漏的问题,需要通过父进程wait, 释放该子进程占用的资源


1. wait

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:
 成功返回被等待进程pid,失败返回-1。
参数:
 输出型参数,获取子进程退出状态,不关心则可以设置成为NUL

测试:

  1 #include <iostream>                                
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <sys/types.h>
  5 #include <sys/wait.h>
  6 #include <unistd.h>
  7 #include <stdio.h>
  8 
  9 using namespace std;
 10 
 11 
 12 int main()
 13 {
 14   pid_t id = fork();
 15 
 16   if(id == 0)
 17   {
 18     int i = 5;
 19     while(i--)
 20     {
 21       printf("child_ PID : %d\n", getpid());
 22       sleep(1);
 23     }
 24     exit(-1);
 25   }
 26 
 27   sleep(10);
 28   pid_t pid = wait(NULL);
 29   printf("father return :%d\n", pid);                                 
 30 
 31 
 32   return 0;
 33 }

image-20220409133545359


2. waitpid

当正常返回的时候waitpid返回收集到的子进程的进程PID

pid_ t waitpid(pid_t pid, int *status, int options);
waitpid(pid, null, 0);//指定子进程
waitpod(-1, null, 0);//任意子进程

3. status参数

  • wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充
  • 如果传递NULL,表示不关心子进程的退出状态信息。 否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程

status是一个整型 linux下4字节,32bit,只使用低16bit,其他未使用

image-20220409140457512


image-20220409144658872


系统提供了宏:

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

  • WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)

if( WIFEXITED(status) && ret == pid )
{
    printf("code is :%d.\n",WEXITSTATUS(status));
}
else
{
     printf("wait child failed, return.\n");
}

4. options参数

**阻塞等待:**一直等到子进程退出。

本质是:

  • **阻塞的本质:**其实是进程的PCB被放入了等待队列,并将进程的状态改为S状态
  • **返回的本质:**进程的PCB从等待队列拿到R队列,从而被CPU调度

**非阻塞等待:**需要多次发出请求询问是否结束,轮询访问

pid_t pid = fork();
int status = 0;
int ret = waitpid(pid, &status, WNOHANG);

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


三、进程的程序替换

如果想要子进程进行一个新的程序

进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变


1. execl进程替换

**execl函数:**如果调用失败,不会执行该代码

int execl(const char *path, const char *arg, ...);
//全路径/文件名    //可变参数列表怎么执行就写什么命令,结束用NULL

image-20220416093038578

  1 #include <iostream>                                
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <sys/types.h>
  5 #include <sys/wait.h>
  6 #include <unistd.h>
  7 #include <stdio.h>
  8 
  9 using namespace std;
 10 
 11 
 12 int main()
 13 {
 14   cout << "hello world" << endl;
 15 
 16   execl("/usr/bin/ls", "ls", "-a", "-l", "-d", NULL);
 17 
 18   cout << "hello world" << endl;
 19 
 20 
 21   return 0;
 22 }

image-20220416103400055


程序替换的本质是把程序的进程代码+数据加载进特定进程的上下文中

C/C++程序运行,必须的先加载到内存中!
如何加载? 加载器:exec*程序替换函数

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支)

子进程调用一种exec函数执行另一个程序,此时发生写实拷贝,不影响父进程


  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 18:25:00  更:2022-04-18 18:28:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 20:26:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码