Linux系统编程基础:进程控制

在这里插入图片描述

文章目录

  • 一.子进程的创建
      • 操作系统内核视角下的父子进程存在形式
      • 验证子进程对父进程数据的写时拷贝
  • 二.进程等待
      • 进程非阻塞等待示例:
  • 三.进程替换
      • 内核视角下的进程替换过程:
      • 综合利用进程控制系统接口实现简单的shell进程

进程控制主要分为三个方面,分别是:子进程的创建,进程等待,进程替换
在这里插入图片描述

一.子进程的创建

  • 父进程调用fork()系统接口创建子进程后,操作系统会为子进程创建独立的PCB结构体虚拟地址空间mm_struct,因此父子进程之间具有互相独立性

操作系统内核视角下的父子进程存在形式

  • 父进程调用fork()函数之后:在这里插入图片描述

验证子进程对父进程数据的写时拷贝

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int g_val = 0;
int main(int argc,const char * argv[])
{//创建子进程pid_t id = fork();if(id < 0){//创建子进程失败,退出主函数perror("fork");return 0;}else if(id == 0)  {//子进程执行流//子进程对变量g_val进行修改,引发写时拷贝g_val=100;printf("childProcess[%d]: %d : %p\n", getpid(), g_val, &g_val);}else{//父进程的执行流//父进程先休眠3秒,让子进程先完成g_val变量的写入sleep(3);printf("parentProcess[%d]: %d : %p\n", getpid(), g_val, &g_val);}sleep(1);return 0;
}
  • 执行结果:在这里插入图片描述
  • 内核视角下,代码段中的写时拷贝图解:在这里插入图片描述
    在这里插入图片描述
  • 写时拷贝保证了父子进程之间互相独立的同时提高了计算机整机的内存使用效率

二.进程等待

  • 子进程退出后会进入僵尸状态,僵尸状态进程的内核数据结构对象会保留在操作系统内核空间中,在父进程读取子进程的退出信息后,操作系统才会释放掉子进程所占用的所有系统资源
    • 若父进程比子进程先退出,那么操作系统就会接管子进程(成为孤儿进程),子进程退出后,操作系统会自动读取子进程的退出信息.
  • 父进程读取子进程的退出信息这一过程称为进程等待
  • 进程等待常用系统接口:int waitpid(int pid, int *status, int options);
    • 形参int pid:在这里插入图片描述

    • 形参int *status:用于记录进程退出码和退出信号的输出型参数

    • 形参int options表示进程等待的方式:主要分为阻塞等待非阻塞等待两大类:

      • option0时:进程执行阻塞等待,此时进程会进入阻塞状态(PCB退出运行队列,进入阻塞队列),直到其所等待的子进程退出,该进程才会重新进入运行状态读取子进程的退出信息
      • option为非零时(比如使用系统宏WNOHANG):进程执行非阻塞等待, 此时进程会尝试读取其子进程的退出信息,若没能读取到子进程的退出信息,则waitpid系统接口立即返回0
    • 返回值int:若waitpid系统接口读取到子进程的退出信息,返回子进程的pid,若waitpid执行过程中出现错误,则返回-1

进程非阻塞等待示例:

#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>int main()
{int pid = 0;//创建子进程pid = fork();if(pid == -1){//子进程创建失败printf("fork failed\n");return -1;}else if(pid == 0){//子进程的代码执行流int cnt = 5;while(cnt--){sleep(1);printf("child process running\n");}exit(11);}else{//父进程的代码执行流//非阻塞等待子进程int status = 0;bool quit = 0;while(quit == 0){//循环非阻塞等待子进程int res =  waitpid(pid,&status,WNOHANG);if(res > 0){//子进程已退出printf("waiting pid success,chilProc exit,退出码:%d\n",WEXITSTATUS(status));quit = 1;}else if(res == 0){//子进程还未退出printf("waiting pid success,childProc still running\n");}else{//等待发生错误printf("waiting pid failed\n");}sleep(1);}}return 0;
}

在这里插入图片描述

三.进程替换

  • 进程替换的概念:通过特定的系统调用接口,操作系统可以将进程当前执行的代码段替换成指定系统路径下其他可执行程序的代码段,然后根据进程从头开始执行新的代码段(因此需要通过进程替换系统接口为新代码段传入main函数命令行参数)

内核视角下的进程替换过程:

在这里插入图片描述
在这里插入图片描述

  • 可见进程替换并不是创建新的进程(进程的PCB虚拟内存结构体不变)
  • 注意:进程替换过程中,一些全局性的数据(比如环境变量)不会被替换掉
  • 进程替换系统接口:
    在这里插入图片描述
  • 形参和返回值统一解释:
    • 参数const char*path:表示将要替换现有代码段的目标可执行程序的完整路径
    • 参数const char*file:表示将要替换现有代码段的目标可执行程序的文件名,其系统路径由环境变量PATH决定
    • 参数const char*arg,...:表示传给新代码段main函数命令行参数的字符串,...表示可变参数列表,可以传入多个字符串,最后一个字符串需传入NULL
    • 参数char *const argv[]:表示传给新代码段main函数命令行参数的字符串数组,数组中最后一个字符串需传入NULL
    • 参数cahr*const envp[]:表示传递给新代码段的环境变量字符串数组
    • 当进程替换失败时,exec系列系统接口会返回-1
  • 实质上,exec*系列系统接口在Linux系统中充当着指令集和数据加载器的角色

综合利用进程控制系统接口实现简单的shell进程

  • shell进程的运行原理:shell进程接收到用户输入的指令后,对指令进行格式化处理,然后创建子进程,子进程通过exec系列系统接口将自身替换成系统命令并执行以响应用户需求,shell进程的这种运行机制保证了自身的进程安全(子进程出现错误不会影响到父进程的运行)
    在这里插入图片描述
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <memory.h>//用户输入的命令行的最大长度
#define CStrLen 1024
//解析命令行得到的格式化字符串数组
#define SStrLen 50
//命令行字符串
char CommStr[CStrLen];
//格式化命令行字符串数组
char*  StdStr[SStrLen];//命令行分隔符
#define Sep " "
//操作系统配置的环境变量
extern char ** environ;
int main()
{while(1) {printf("[我的命令行解释器 myshell]$ ");fflush(stdout);memset(CommStr,'\0',sizeof StdStr);//获取用户输入命令if(fgets(CommStr,sizeof CommStr,stdin)== NULL){continue;}CommStr[strlen(CommStr)-1] = '\0';StdStr[0] = strtok(CommStr,Sep);//根据空格对用户输入的字符串进行分割并存入StdStr字符串数组中int i = 1;while(StdStr[i++] = strtok(NULL,Sep));//部分命令(比如cd命令)需要由shell进程自己来执行if(strcmp(StdStr[0],"cd")== 0){//用chdir函数改变shell进程的工作路径if(StdStr[1] != NULL){chdir(StdStr[1]);}continue;}//shell创建子进程来执行系统命令int pid = fork();if(pid == 0){//printf("shell的子进程执行系统命令:\n");execvp(StdStr[0],StdStr);printf("-mybash: %s: command execute failed\n",StdStr[0]);exit(-1);}else{int status;//父进程进行阻塞等待,等待子进程执行完系统命令结束并获取其退出码int waitres = waitpid(pid,&status,0);if(waitres == -1){printf("waitchild process failed\n");}}}return 0;
}

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

html 边缘融合加载

html 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>边缘融合加载</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}body {height: 100vh;padding-bottom: 80px;b…

【Java每日一题】— —第二十题:杨辉三角(直角三角形)。(2023.10.04)

&#x1f578;️Hollow&#xff0c;各位小伙伴&#xff0c;今天我们要做的是第二十题。 &#x1f3af;问题&#xff1a; 杨辉三角&#xff08;直角三角形&#xff09;。 解法1 第一步:动态初始化 第二步:为主对角线及第一列的元素赋值1 第三…

用于工业物联网和自动化的 Apache Kafka、KSQL 和 Apache PLC4

由于单一系统和专有协议&#xff0c;数据集成和处理是工业物联网&#xff08;IIoT&#xff0c;又名工业 4.0 或自动化工业&#xff09;中的巨大挑战。Apache Kafka、其生态系统&#xff08;Kafka Connect、KSQL&#xff09;和 Apache PLC4X 是以可扩展、可靠和灵活的方式实现端…

【数据科学】Scikit-learn[Scikit-learn、加载数据、训练集与测试集数据、创建模型、模型拟合、拟合数据与模型、评估模型性能、模型调整]

这里写目录标题 一、Scikit-learn二、加载数据三、训练集与测试集数据四、创建模型4.1 有监督学习评估器4.1.1 线性回归4.1.2 支持向量机(SVM)4.1.3 朴素贝叶斯4.1.4 KNN 4.2 无监督学习评估器4.2.1 主成分分析(PCA)4.2.2 K Means 五、模型拟合5.1 有监督学习5.2 无监督学习 六…

行高的继承和消除内外边距

行高的继承性 <style>div {font: 12px/1.5 Microsoft yahei;} ​p {font-size: 14px;}</style> <body><div><p>苏丹红事件</p></div> <body> 12px这里没有行高没有写单位&#xff0c;子类继承父类的1.5倍&#xff0c;就是14*…

毅速3D打印:深骨位零件制造首选3D打印

在模具制造领域&#xff0c;深骨位零件由于其复杂形状和结构&#xff0c;传统的加工方法往往难以满足生产要求&#xff0c;导致产品不良问题频繁出现。而如今&#xff0c;随着3D打印技术的普及&#xff0c;深骨位零件在3D打印面前变得不再困难。 3D打印是一种快速成型技术&…

王杰国庆作业day6

服务器 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <my_head.h> #define PORT 2324 //端口号 #define IP "192.168.10.107" //本机IP int main(int argc, const char *argv[]) {sqlite3* d…

C++标准模板(STL)- 类型支持 ()

对象、引用、函数&#xff08;包括函数模板特化&#xff09;和表达式具有称为类型的性质&#xff0c;它限制了对这些实体所容许的操作&#xff0c;并给原本寻常的位序列提供了语义含义。 附加性基本类型及宏 实现定义的空指针常量 NULL 定义于头文件 <clocale> 定义于…

linux——信号

✅<1>主页&#xff1a;&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux——进程等待 ☂️<3>开发环境&#xff1a;Centos7 &#x1f4ac;<4>前言&#xff1a;生活中处处有信号&#xff0c;linux中也有很多信号&#xff0c;OS使…

Elasticsearch安装并使用Postman访问

Elasticsearch&#xff0c;一个强大的开源搜索和分析引擎&#xff0c;已经在全球范围内被广泛应用于各种场景&#xff0c;包括网站搜索、日志分析、实时应用等。由于其强大的功能和灵活性&#xff0c;Elasticsearch 已经成为大数据处理的重要工具。然而&#xff0c;对于许多初次…

设计模式11、享元模式Flyweight

解释说明&#xff1a;享元模式&#xff08;Flyweight Pattern&#xff09;运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象&#xff0c;而这些对象都很相似&#xff0c;状态变化很小&#xff0c;可以实现对象的多次复用。 抽象享元类&#xff08;Flyweight&…

【记录】IDA|IDA怎么查看当前二进制文件自动分析出来的内存分布情况(内存范围和读写性)

IDA版本&#xff1a;7.6 背景&#xff1a;我之前一直是直接看Text View里面的地址的首尾地址来判断内存分布情况的&#xff0c;似乎是有点不准确&#xff0c;然后才想到IDA肯定自带查看内存分布情况的功能&#xff0c;而且很简单。 可以通过View-Toolbars-Segments&#xff0c…

竞赛选题 机器视觉人体跌倒检测系统 - opencv python

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 机器视觉人体跌倒检测系统 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&…

Kafka日志索引详解以及生产常见问题分析与总结

文章目录 1、Kafka的Log日志梳理1.1、Topic下的消息是如何存储的&#xff1f;1.1.1、 log文件追加记录所有消息1.1.2、 index和timeindex加速读取log消息日志。 1.2、文件清理机制1.2.1、如何判断哪些日志文件过期了1.2.2、过期的日志文件如何处理 1.3、Kafka的文件高效读写机制…

MySQL-MVCC(Multi-Version Concurrency Control)

MySQL-MVCC&#xff08;Multi-Version Concurrency Control&#xff09; MVCC&#xff08;多版本并发控制&#xff09;&#xff1a;为了解决数据库并发读写和数据一致性的问题&#xff0c;是一种思想&#xff0c;可以有多种实现方式。 核心思想&#xff1a;写入时创建行的新版…

【多任务案例:猫狗脸部定位与分类】

【猫狗脸部定位与识别】 1 引言2 损失函数3 The Oxford-IIIT Pet Dataset数据集4 数据预处理4 创建模型输入5 自定义数据集加载方式6 显示一批次数据7 创建定位模型8 模型训练9 绘制损失曲线10 模型保存与预测 1 引言 猫狗脸部定位与识别分为定位和识别&#xff0c;即定位猫狗…

MacOS怎么安装Nacos(附带:Windows系统)

MacOS安装Nacos&#xff08;一定要配置JDK的环境变量&#xff0c;后面告诉你为什么&#xff1f;&#xff09; &#xff08;1&#xff09;进入Nacos官网&#xff0c;前往githubhomehomehttp://nacos.io/zh-cn/ &#xff08;2&#xff09;点击右下角的releases 然后点击Tags 选择…

代码随想录算法训练营第五十七天 | 392.判断子序列 115.不同的子序列

1. 判断子序列 392. 判断子序列 - 力扣&#xff08;LeetCode&#xff09; dp[i][j] 表示以下标i-1为结尾的字符串s&#xff0c;和以下标j-1为结尾的字符串t&#xff0c;相同子序列的长度。 class Solution {public boolean isSubsequence(String s, String t) {//dp[i][j] 表示…

Redis7的数据结构

Redis以键-值对的形式存储数据 一、键 1、键的特点 键是一个字符串&#xff0c;这个字符串的内容可以是数字、字符序列&#xff0c;也可以是一个文件的字节序列&#xff0c;甚至空字符串也可以做为key。 在一个数据库中键必须是唯一的。 键最大可以达到512M&#xff0c;但太…

通用收藏管理器Koillection

什么是 Koillection &#xff1f; Koillection 是一个自托管的收藏管理器&#xff0c;旨在跟踪任何类型的物理&#xff08;主要&#xff09;收藏&#xff0c;如书籍、DVD、邮票、游戏……&#xff0c;由于 Koillection 旨在用于任何类型的收藏&#xff0c;它不支持自动下载元数…