探索Linux中的进程控制:从启动到退出的背后原理

个人主页:chian-ocean

文章专栏-Linux

前言:

进程控制是操作系统对进程的创建、运行、调度、中止等活动进行管理和协调的行为。它是操作系统中至关重要的一部分,保证多任务处理环境下的资源分配和系统稳定性。

在这里插入图片描述

进程创建

fork( )

  • fork() 调用后:

    • 子进程是父进程的副本,拥有相同的代码和数据。
    • 子进程的所有资源(如内存、打开的文件描述符)最初与父进程共享,但在写入数据时会触发**写时复制(Copy-on-Write,COW)**机制。

    返回值:

    • **在父进程中:**返回子进程的 PID(进程 ID)。
    • **在子进程中:**返回 0
    • **如果失败:**返回 -1 并设置错误码(通常是因为系统资源不足)
int main()
{
    pid_t id = fork();
    if(id > 0){
        while(1){
        cout << "父进程"<< "pid :"<<getpid() <<endl; 
        sleep(2);
        }      
    }
    else if(id == 0){
        while(1)
        {   
        cout << "子进程"<<endl;
        sleep(2);                     
        }
    }
    else 
    {
        perror("fork");
        cout << "子进程"<< "pid :"<<getpid() <<endl;
        sleep(2);
        }
    }
    else 
    {
        perror("fork");
    }
    return 0;
}

执行代码

在这里插入图片描述

进程退出(终止)

进程终止是操作系统中一个进程完成任务或由于某种原因被终止运行的过程。在进程终止后,操作系统会释放该进程占用的资源,并将其从系统中的进程表中移除

退出码

退出码是进程在退出时返回给操作系统或父进程的一个状态值,表示进程的退出状态。退出码常用于判断进程是否成功完成任务或发生了错误

成功退出:

  • 退出码为 0,表示进程正常结束,没有错误。
  • 这也就是为什么默认return 0

失败退出:

  • 0 值通常表示进程发生了错误或异常。
  • 不同的退出码可以表示不同的错误原因(由程序员定义)。

检查退出码

#终端检查
echo $?

demo

  • 在这里面设置退出码为 8 ,以便观察。
#include <iostream>    
#include <unistd.h>    
#include <stdlib.h>    
    
using namespace std;    
    
    
int main()    
{    
    int i = 10;    
    while(i--)    
    {    
        cout << i <<" ";    
    }    
    cout << endl;    
    return 8;    
}

执行

在这里插入图片描述

进程退出的方式

  • **正常退出:**主函数执行到最后,正常返回。
  • **异常退出:**发生异常(如段错误、非法访问内存、除以零)导致进程被操作系统终止。

正常退出

主函数返回:

  • 主函数(main())返回值即为进程的退出码。

调用 exit() 函数:

  • 显式终止进程,返回退出码。
  • 执行清理操作(如刷新缓冲区、关闭文件等)。
#include <iostream>      
#include <unistd.h>      
#include <stdlib.h>      
                
using namespace std;      
                
int func()      
{               
    cout << "调用func"<<endl;      
    exit(1);      
                
    return 1;      
}               
                
int main()      
{                                                                                                                                   
      
    int funcret = func();      
    cout << funcret << endl;      
    return 0;                     
} 

代码功能说明

  1. func 函数
    • 输出一条消息:调用func
    • 调用 exit(1) 直接终止程序,返回退出码 1
    • 后面的 return 1 永远不会被执行,因为 exit(1) 会导致程序立即退出。
  2. main 函数
    • 调用 func()
    • 由于 func() 中调用了 exit(1),程序会立即退出,func 返回值永远不会被赋给 funcret
    • main 中的 cout << funcret << endl;return 0; 永远不会被执行。

在这里插入图片描述

_exit和exit

**_exit()不会执行任何用户态的清理工作,直接终止进程,不会:

  1. 调用 atexit() 注册的清理函数。
  2. 刷新标准 I/O 流。
  3. 关闭打开的文件缓冲区。
#include <iostream>
#include <unistd.h>
using namespace std;
int main()    
{    
    cout << "This is exit"<< endl;    
    cout << "This will not be flushed.";  // 没有换行符,缓冲区未刷新    
    exit(0);  // 直接终止程序,刷新缓冲区  
    
    cout << "This is _exit"<< endl;    
    cout << "This will not be flushed.";  // 没有换行符,缓冲区未刷新    
    _exit(0);  // 直接终止程序,不刷新缓冲区                                                    
    return 0;    
}

cout << "This is exit << endl;":

  • 输出 "This is exit" 并刷新缓冲区。
  • 输出立即显示在屏幕上。

cout << "This will not be flushed.";:

  • 输出内容存储在缓冲区中,但未刷新(没有换行符)。

_exit(0);:

  • 程序立即终止,不刷新缓冲区。
  • "This will not be flushed." 不会被输出,因为缓冲区未刷新。

在这里插入图片描述

returnexit()_exit() 总结对比表

特性/行为returnexit()_exit()
作用范围退出当前函数,返回控制权给调用者终止整个程序,返回控制权给操作系统立即终止当前进程,不返回控制权
适用范围函数正常结束,返回值给调用者程序正常或错误退出,需要完成清理工作子进程退出或紧急情况下立即终止程序
I/O 缓冲区刷新自动刷新(如果退出程序)刷新所有标准 I/O 缓冲区不刷新标准 I/O 缓冲区
atexit() 注册函数不调用调用所有通过 atexit() 注册的清理函数不调用
局部变量析构调用局部变量的析构函数(C++ 对象)不调用析构函数不调用析构函数
性能性能高,适用于正常函数返回较慢,涉及缓冲区刷新和清理操作性能最高,直接调用系统内核
适用场景函数正常结束,逻辑返回值给调用者程序终止,需要完成缓冲区刷新和清理工作子进程退出或需要立即终止进程时
调用位置仅在当前函数中有效可在程序任意位置调用可在程序任意位置调用

异常退出

异常终止的表现

非零退出码:表示异常终止的原因。

#include<iostream>
using namespace std;
int main()
{
    int a = 10, b = 0;
	int c = a / b;  // 除以零导致异常终止
	cout << c << endl;
}

执行代码

在这里插入图片描述

常见退出码:

退出码原因
139段错误(SIGSEGV)。
136浮点异常(SIGFPE)。
1一般错误。
6调用 abort()SIGABRT)。
9强制终止(SIGKILL
# 查看错误信号
kill -l

在这里插入图片描述

错误码

打印错误码

#include <iostream>    
#include <cerrno>    
#include <cstring>        
using namespace std;        
int main()    
{    

    for(int i = 0; i < 135; i++)    
    {    
        const char * errmessage = strerror(i);    
        if(errmessage)    
        {    
            cout<< "code error" <<" "<< i <<":"<< errmessage <<endl;     
        }    
    }    
    
    return 0;       
}

执行代码

在这里插入图片描述

  • 可以观察到默认0编码是success
  • 这里面只显示一部分
  1. 标准错误码:
    • 通常范围是 1 到 134,其中每个错误码都由 POSIX 标准定义,常见于 errno.h
  2. 系统特定错误码:
    • 某些错误码可能特定于操作系统,错误描述可能不同。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【ComfyUI】python调用生图API,实现批量出图

官方给的示例&#xff1a; https://github.com/comfyanonymous/ComfyUI/blob/master/script_examples/websockets_api_example.pyhttps://github.com/comfyanonymous/ComfyUI/blob/master/script_examples/websockets_api_example.pyhttps://github.com/comfyanonymous/ComfyU…

推箱子游戏

java小游戏2 一游戏介绍 二图像准备 墙、箱子、人、箱子目的地&#xff0c;人左边、人右边、人上边、人下边 三结构准备 地图是什么&#xff0c;我们把地图想象成一个网格&#xff0c;每个格子就是工人每次移动的步长&#xff0c;也是箱子移动的距离&#xff0c;设置一个二维数…

软件鉴定测试重要性和流程分享

在当今快速发展的数字时代&#xff0c;软件系统的可靠性和安全性变得至关重要。越来越多的企业意识到&#xff0c;进行专业的软件鉴定与测试不仅是保证产品质量的必要步骤&#xff0c;也是提升市场竞争力的重要手段。软件鉴定测试指通过对软件进行评估和验证&#xff0c;以确保…

Linux C\C++编程-建立文件和内存映射

【图书推荐】《Linux C与C一线开发实践&#xff08;第2版&#xff09;》_linux c与c一线开发实践pdf-CSDN博客 《Linux C与C一线开发实践&#xff08;第2版&#xff09;&#xff08;Linux技术丛书&#xff09;》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 Linu…

15-spring整合mybatis方式一

spring整合mybatis 方式一【重要】 步骤: 1.导入相关jar包 junit mybatis mysql数据库 spring相关的 aop织入 mybatis-spring 【new】 junit junit 4.12 mysql mysql-connector-java 8.0.23 org.mybatis mybatis 3.5.2 org.springframework spring-webmvc 5…

基于深度学习的视觉检测小项目(十五) 用户的登录界面

用户管理离不开的是消息框&#xff08;QMessageBox&#xff09;和对话框&#xff08;QDialog&#xff09;&#xff0c;比如对话框用于用户名和密码输入&#xff0c;消息框用于提示登录成功、密码错误。 • 基础知识&#xff1a;PySide6&#xff08;PyQT5&#xff09;的常用对话…

什么是COLLATE排序规则?

在当今数字化世界中&#xff0c;数据的整理、比较和排序是至关重要的。在数据库管理和编程语言中&#xff0c;我们经常需要对字符串进行排序&#xff0c;以展示或处理信息。为了实现这一点&#xff0c;各种系统和工具提供了排序规则&#xff0c;其中COLLATE排序规则就是其中的一…

Linux:信号的保存[2]

1.信号在内核中的表示 因为是三种内核的数据结构&#xff0c;操作系统就可以通过操作这些数据结构提供接口。 如果一个信号没有产生&#xff0c;并不妨碍它可以先被阻塞。 当同一时刻发送大量相同信号时&#xff0c;会丢失。 2.信号的捕捉&#xff08;重点&#xff09; 信号产…

顺序表和链表(详解)

线性表 线性表&#xff08; linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的一条直线。…

【电脑无法通过鼠标和键盘唤醒应该怎么办】

【电脑无法通过鼠标和键盘唤醒应该怎么办】 方法一(有时候不起作用):方法二(方法一无效时,使用方法二): 方法一(有时候不起作用): 方法二(方法一无效时,使用方法二):

动态规划(路径问题)

62. 不同路径 62. 不同路径 - 力扣&#xff08;LeetCode&#xff09; 动态规划思想第一步&#xff1a;描述状态~ dp[i][j]&#xff1a;表示走到i&#xff0c;j位置时&#xff0c;一共有多少种方法~ 动态规划思想第二步&#xff1a;状态转移方程~ 动态规划思想第三步&#xf…

vue + element-ui 组件样式缺失导致没有效果

失效 代码&#xff1a; 修改方法&#xff1a; 在main.js文件里面加上&#xff1a; import element-ui/lib/theme-chalk/index.css; 最后&#xff1a;

Go 切片:用法和本质

要想更好的了解一个知识点&#xff0c;实战是最好的经历。 题目 我这里放一道题目&#xff1a; package mainimport "fmt"func SliceRise(s []int) {s append(s, 0)for i : range s {s[i]}fmt.Println(s) }func SlicePrint() {s1 : []int{1, 2}s2 : s1s2 append…

Spring MVC:设置响应

目录 引言 1. 返回静态页面 1.1 Spring 默认扫描路径 1.2 RestController 1.2.1 Controller > 返回页面 1.2.2 ResponseBody 2. 返回 HTML 2.1 RequestMapping 2.1.1 produces(修改响应的 Content-Type) 2.1.2 其他属性 3. 返回 JSON 4. 设置状态码 4.1 HttpSer…

基于Spark的共享单车数据存储系统的设计与实现_springboot+vue

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

在Unity中使用大模型进行离线语音识别

文章目录 1、Vosk下载下载vosk-untiy-asr下载模型在项目中使用语音转文字音频转文字2、whisper下载下载unity项目下载模型在unity中使用1、Vosk 下载 下载vosk-untiy-asr Github链接:https://github.com/alphacep/vosk-unity-asr 进不去Github的可以用网盘 夸克网盘链接:h…

【计算机网络】- 应用层HTTP协议

目录 初识HTTP 什么是HTTP 版本 HTTPS 模型 HTTP抓包工具 为什么使用 抓包工具的下载 下载后的重要操作 Fiddler的使用 HTTP请求与响应的基本格式 HTTP请求基本格式​编辑 HTTP响应基本格式 协议格式总结❗️❗️❗️​编辑 HTTP 详解 认识 URL URL基本格式 …

记一次IDOR 和访问控制缺失漏洞挖掘

视频教程在我主页简介和专栏里 测试 IDOR&#xff08;不安全的直接对象引用&#xff09; 漏洞时&#xff0c;我会使用一系列工具&#xff0c;确保不会遗漏任何问题。以下是我的测试方法&#xff1a; 设置 Firefox 和 Pwnfox&#xff1a; 1、我使用 Firefox 浏览器&#xff0c…

GS论文阅读--Hard Gaussian Splatting

前言 本文也是对高斯点云的分布进行优化的&#xff0c;看&#xff01; 文章目录 前言1.背景介绍2.关键内容2.1 位置梯度驱动HGS2.2 渲染误差引导HGS 3.文章贡献 1.背景介绍 在训练过程中&#xff0c;它严重依赖于视图空间位置梯度的平均幅度来增长高斯以减少渲染损失。然而&…

JS基础-操作数组(7)

一.增删改查 1.改 重新赋值 2.增 arr.puch() 末尾追加 arr.unshift() 开头追加 a)案例&#xff1a;数组筛选 3.删除 arr.pop() 删除最后一个元素 arr.shift() 删除第一个元素 splice&#xff08;&#xff09; 删除指定元素