Linux——进程控制(一)进程的创建与退出

SIPVicious实战指南:从零开始掌握VoIP渗透测试(Kali Linux环境) 本文为SIPVicious实战指南,详细介绍了在Kali Linux环境下进行VoIP渗透测试的完整流程。从环境准备与工具安装开始,逐步讲解如何使用svmap扫描SIP服务器、svwar枚举PBX分机号,以及svcrack进行密码安全测试,并整合svreport生成报告。旨在帮助安全从业者从零开始,系统掌握这套经典开源工具,在授权范围内有效评估VoIP系统的安全性。 阅读详情

目录

一、进程创建

1.写时拷贝

2.创建多个进程

二、进程终止

1.main函数的返回值

2.bash中的$? 

3.自定义退出码

4.C语言的错误码

5.错误码与退出码的区别

6.代码异常终止

7.exit函数

8.总结


一、进程创建

在之前,我们学过linux中的非常重要的函数——fork。他可以从已存在进程中创建一个新进程,新进程为子进程,而原进程为父进程。

1.写时拷贝

我们知道,fork之后,父子代码共享,经常会出现同一个变量,父子通过操作的不同,这个变量的值也不同,这个时候就会发生写时拷贝。写时拷贝是如何进行的呢?

通过这张图可以看到,fork之后数据段变成了只读, 子进程需要对数据进行写入,就得需要写时拷贝,写时拷贝需要重新申请空间,进行拷贝,再修改页表,这都是操作系统在帮我们处理的,那么操作系统怎么知道你这一份数据需要进行写时拷贝呢?

父进程创建子进程的时候首先将自己的读写权限修改成只读,然后再创建子进程,这些操作用户并不知道,可能对某些数据进行写入,这样在页表处就会进行权限判断,发现用户没有权限,操作系统此时就会介入,操作系统会判断用户的操作

如果该区域本该是可读可写的,是操作系统修改为只读的,因此操作系统会认为用户的操作不算错误,就会触发重新申请内存再拷贝内容的策略机制,这就是写时拷贝。

如果出错,就直接报错,不做额外处理。

写时拷贝完成后,再将对应的内容在页表中修改为可读可写(没有进行写实拷贝的内容依然是只读的)。这样用户就可以正常访问了。

这是一种惰性分离,每次发生写时拷贝都要开辟空间,将写时拷贝的时间越往后延迟,操作系统就有更多的资源。


这里还有一个小问题:你要写入的时候写就完事了,为何还要拷贝一份呢?

因为覆盖和修改是不一样的,很多情况,我们只是想要修改内容的某一部分,这样先拷贝再修改会更合适一点。

2.创建多个进程

我们知道fork的常规用法如下两种

  • 一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子 进程来处理请求。
  • 一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。

如果要创建多个进程来帮我们处理,应该怎么做呢?  直接上代码

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

#define N 10

typedef void (*callback)();

void Work()
{
    int cnt = 10;
    while(cnt)
    {
        printf("我是一个子进程, pid: %d, ppid :%d, cnt:%d\n",getpid(),getppid(),cnt--);
        sleep(1);
    }
}

void CreateProcess(int n,callback cb)
{
    int i = 0;
    for(;i<n;i++)
    {
        sleep(1);
        pid_t id = fork();
        if(id == 0)
        {
            //child                                                                    
            printf("子进程创建成功: %d\n",i);
            cb();
            exit(0);
        }
    }
}

int main()
{
    CreateProcess(N,Work);
    sleep(100);
    return 0;
}

这代码对于学过fork的我们来讲,并不算难,多了一个函数指针而已,下面是运行代码。

二、进程终止

进程退出的场景如下三种

  • 代码运行完毕,结果正确
  • 代码运行完毕,结果不正确
  • 代码异常终止

1.main函数的返回值

我们写C语言程序时,main函数一般都会return 0。只要执行到了return语句,证明我们的代码肯定是运行完毕了的,只是结果还不知道是否正确。

在多进程环境中,我们创建子进程的目的是完成父进程不方便办的事,那我们怎么知道子进程办得怎么样,虽然我们可以打印出来看看结果,但在有一些情况下不方便或者不能打印出来看看,此时就可以通过return的值来查看的,main函数的返回值,就叫做进程的退出码,0通常表示成功,非0表示失败。父进程可以通过获取子进程退出码(即main函数的返回值)来得知子进程做得咋样。

成功的还好,知道你吧事情办得很好,如果返回非0,代表这个事没办好,我们得知道是因为什么原因失败的,我们可以用不同的数字表示不同的原因。但纯数字能表示出错的原因,但是不便于人阅读,因此有一个函数交 strerror 函数。

如下可以打印出strerror各个数字代表的出错原因

有很多很多原因 

2.bash中的$? 

在bash命令中输入echo $? 可以打印出最近一个子进程执行完毕时的退出码,有点类似于之前我们学习的环境变量,变量名为?,加了$可以打印出变量里的内容。

如下代码中return 10,执行该进程,bash最后获取到的子进程退出码就为10

但是我们继续执行echo $? 后面退出码就会变成0,因为echo也是bash的一个子进程,执行echo语句后,echo语句就是最后一个子进程了,echo又是正常退出的,因此再输入echo $? 得到的值为0。

main函数的退出码是可以被父进程获取的,用来判断子进程的运行结果 

3.自定义退出码

退出码可以使用C语言内置的,也可以自定义,自己对退出码做解释,因为退出码退出多少(也就是return 返回多少是你自己设置的) 

如下就是自定义的退出码,如果你的代码根据用户的操作出现了错误,可以返回响应的值,来知道发生了什么错误。

4.C语言的错误码

在学习C语言的时候,我们接触过一个名叫 errno 的全局变量,他会在程序在运行过程中调用某些库函数或者系统接口出错的时候,被自动设置。也是记录最后一次出错的信息。

如下代码,只读的方式打开一个不存在文件,我们看一下erron的变化与出错信息

发现错误码为2,错误信息为没有该文件

5.错误码与退出码的区别

  • 错误码通常是衡量调用库函数或者系统调用接口的调用情况。(系统调用也能更改错误码是因为Linux是用C语言写的,提供了C式接口)
  • 退出码通常是一个进程退出的时候,他的退出结果。

他们两个共同的地方在于当失败的时候,用来衡量函数、进程出错时的详细原因。

如下,让错误码与退出码保持了一致

6.代码异常终止

前面五点主要学习的是进程正常退出的问题,可能会有出错码和退出码,如果一个进程异常终止,那么他的退出码也就没有了意义。

比如代码中存在 /0 错误,又比如段错误,栈溢出等等,程序就会崩溃,进程就异常了,就不会继续运行了,本质是操作系统将该进程杀掉了,操作系统会用信号的方式将进程杀掉。

输入 kill -l 可以查看 kill命令的信号 

这里我们一直运行一个进程,然后输入kill -8 + 进程pid,就可以通过浮点数错误的方式终止该进程。输入其他方式杀死,也会有相应的错误报告。 

 因此,查看进程是否出现异常,我们只需看有没有收到信号即可。

7.exit函数

C语言退出函数 exit() ,括号内部可以添加数字,这也是退出码的一种。 

exit与return的区别在于:

在非main函数中return 并不会终止进程,main函数会终止进程。

在任意函数中exit都会终止进程。

8.总结

查看进程运行完毕,结果是否正确,只需要看退出码即可

查看进程异常终止,只需要查看收到的信号是什么即可。

openclaw-cn : 无法将“openclaw-cn”项识别为 cmdlet、函数、脚本文件或可运行程序的名称 解决方案 本文主要介绍了openclaw-cn : 无法将“openclaw-cn”项识别为 cmdlet、函数、脚本文件或可运行程序的名称解决方案,希望能对使用openclaw-cn的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案 阅读详情

相关推荐

cocos2dx中DrawNode画线锯齿和非凸多边形填充

记录一下在cocos2dx中使用DrawNode所遇到的2个问题 1.画线锯齿问题 ios版本下,在AppController.mm中设置CCEAGLView的multiSampling和numberOfSamples。如下图 CCEAGLView *eaglView = [CCEAGLView viewWithFrame: [window bounds]

hello-world 5413

Linux进程——进程的退出、子进程退出的收集、孤儿进程

进程退出主要分为两种:正常退出、异常退出正常退出分为以下几种:1.main函数调用return 2.进程调用exit(),标准c库 3.进程调用 _exit() 或者 _Exit() ,属于系统调用 4.进程最后一个线程返回 5.最后一个线程调用pthread exit(4和5与线程有关)异常退出分为以下几种:1.调用abort函数 2.当进程收到某些信号时,如 ctrl+C 3最后一个线程对取消 (cancellation) 请求做出响应退出函数分别有exit()、_exit()、_Exit(),其函数原

2301_78772787的博客 1123

Qt6导入QtChart绘制图表(添加组件)

我在按照大佬们的说明添加QtChart时发现,我的电脑上并不能正确的添加QtChart并编译通过,所以在综合了两位大佬的说明又自己探索了一番后,正确编译通过,分享出来,以便同志们节省一些时间。

Nuaa0719301zyx的博客 2950

Linux中进程的退出

Linux进程退出

weixin_61701822的博客 4469

电路仿真软件PSIM简介

PSIM的基本使用操作...

qq_55203246的博客 7174

STM32单片机远程升级

stm32远程升级

fang_yang_wa的博客 1万+

Linux进程退出详解(do_exit)--Linux进程的管理与调度(十四))

日期 内核版本 架构 作者 GitHub 优快云 2016-05-12 Linux-4.6 X86 & arm gatieme LinuxDeviceDrivers Linux进程管理与调度 Linux进程的退出linux下进程退出的方式正常退出 从main函数返回return 调用exit 调用_exit 异常退出 调用abort 由信号终止 _exit

OSKernelLAB(gatieme) 2万+

PubMedBERT:生物医学NLP中的垂直领域预训练实践与性能突破

本文深入探讨了PubMedBERT在生物医学NLP领域的应用与性能突破。作为专为生物医学文本设计的预训练模型,PubMedBERT通过全词掩码策略和BLURB基准测试,显著提升了命名实体识别、关系抽取等任务的准确率。文章还提供了PubMedBERT的实战应用案例和代码示例,展示了其在医学文献检索和电子病历结构化中的卓越表现。

kite3的博客 283

Linux进程操作(进程环境--程序的启动和退出)

进程环境进程环境程序的启动和退出在shell中启动一个程序加载一个程序加载地址退出程序 进程环境 程序的启动和退出 在shell中启动一个程序 Linux shell 本身可以运行两种文件:二进制可执行文件和解释器文件(例如shell脚本); 启动一个程序的方法: $ 程序的路径名 命令行参数 //例如: ./hello 参数说明: 程序的路径问题:shell 本身有一个环境变量PATH,其中包含有shell所要搜寻的路径。如果指定了一个程序路径名,shell 可以直接到指定的路径搜索用户要执行的文件

Mzcc_bbms的博客 1149

nvidia系列教程-AGX-Orin usb3.0接口调试

NVIDIA Jetson AGX Orin 是一款高性能的嵌入式计算平台,适用于 AI 推理、机器人、自动驾驶等应用场景。本文将介绍如何对 AGX Orin 平台上的 USB 3.0 接口进行调试,包括硬件检查、软件配置以及常见问题的排查。本文主要介绍在AGX-Orin平台开启两个usb3.0口的方法。通过以上步骤,您可以有效地调试和优化 NVIDIA Jetson AGX Orin 上的 USB 3.0 接口。

flypig has a dream! 1500

【Python搞定车载自动化测试】——Python实现车载以太网DoIP刷写(含Python源码)

随着智能电动汽车行业的发展,汽车=智能终端+四个轮子,而人工智能也发展越来越快,Python语言使用越来越广,本章节主要介绍如何使用Python语言基于Pytest自动化框架来实现DoIP诊断自动化测试。首先回顾一下DoIP诊断基础知识:DoIP(Diagnosis over Internet Protocol)是一种用于车辆诊断的网络通信协议。它基于现代互联网技术,允许通过以太网或IP网络进行车辆诊断和通信。

测试领域技术分享 3793

Liunx — 进程等待 (wait和waitpid函数)

进程等待

阿亮的博客 1935

uniapp(全端兼容) - 超详细接入百度统计功能,给uniapp全平台各端项目引入添加百度统计的插件统计流量详细的步骤教程(提供最新的百度统计源代码,详细的示例代码复制粘贴即可快速搞定!)

uniapp h5 app 使用加入接入百度统计,uniapp百度统计,uniapp详细引入百度统计的教程,uniapp接入百度统计,uniapp如何实现加入百度的统计代码,uniapp怎么植入百度统计详细教程,uniapp如何对接百度统计,uniapp百度统计不生效怎么办,uniapp使用百度统计不生效常见问题,uniapp引入百度统计后没有生效,uniapp h5网页接入百度统计代码后没有统计无效,uniapp最新接入使用百度统计功能,uniapp增加百度统计代码,uniapp app如何接入百度统计,

✅ 精选推荐文章 1万+

【Linux】进程的控制①之进程创建与进程退出

enum{open_err,malloc_err可以这样来使用:defult :那么当我们要使用的时候直接调用这个接口就好。结论:mian函数return返回时,表示进程已经退出,return后跟的数字是进程退出码,可以自行设置退出码的字符串意义。

m0_71503225的博客 1987

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【linux进程控制(一)】进程创建&退出-->fork&退出码详谈

本文深入探讨了Linux进程控制中的fork函数和进程退出机制。fork函数创建子进程时会产生两个返回值,这是由于fork内部已创建子进程并执行两次return语句。进程退出分为正常退出和异常退出。exit和_exit的区别在于是否刷新缓冲区,其中exit是_exit的封装。文章还解释了进程独立性导致的写时拷贝现象,以及退出码的含义和查看方法。

熬夜秃顶中...... 2023

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

【linux】进程控制——进程创建,进程退出,进程等待

一个进程创建了另一个进程,创建者为父进程,被创建者为子进程。父进程可以创建多个子进程。操作系统是一号进程,所有进程构成一颗多叉树结构。每个父进程只对直系的子进程负责。父进程创建子进程的一整套流程为:创建子进程——>子进程完成任务——>父进程回收子进程父进程先退,子进程未退。此时子进程的父亲进程被改为1号进程(操作系统),那么该子进程被称为孤儿进程父进程未退,子进程先退。但父进程没有读取到子进程的退出(进程等待),该子进程的状态被改为 Z 状态,Z 状态的进程被成为僵尸进程。

2301_79796701的博客 2706

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Linux进程控制【创建、终止、等待】

进程创建后,需要对其进行合理管理,光靠OS是无法满足我们的需求的,此时可以运用进程控制相关知识,对进程进行手动管理,如创建进程、终止进制、等待进程等,其中等待进程可以有效解决僵尸进程问题

北 海的博客 7700

【Linux指南】进程控制系列(二)进程终止 —— 退出场景、方法与退出码详解

本文深入解析了Linux进程终止的本质、退出场景和三种退出方法。进程终止的核心是释放系统资源(内核结构、内存、文件描述符等),而非简单停止运行。进程退出分为三大场景:正常执行完毕(结果正确/错误)和异常崩溃(如除零错误)。重点对比了三种退出方法:return仅在main函数有效;exit会执行清理操作并刷新缓冲区;_exit直接终止进程不做任何清理。通过代码示例验证了exit和_exit在缓冲区处理和清理函数调用上的关键差异,帮助开发者理解如何选择合适的进程退出方式。

倔强的石头的博客 2万+

【Linux】进程控制(一):进程的创建和终止

在计算机科学的演进历程中,进程概念的出现标志着操作系统设计从批处理系统向多任务系统的重大飞跃。进程作为现代操作系统资源分配的基本单位,其创建、执行与终止构成了计算机程序生命周期管理的核心框架。Linux作为开源操作系统的典范,其进程管理机制体现了Unix哲学的简洁与优雅。本文旨在深入剖析Linux系统中进程创建的关键技术fork函数、进程终止的多种方式及其内在原理,为读者呈现一幅进程生命周期管理的清晰画卷。理解这些底层机制不仅是系统编程的基石,更是洞察操作系统设计思想的窗口。

qq_2778465975的博客 2341

【Linux学习】深入探索进程等待与进程退出码和退出信号

【Linux学习】深入探索进程等待与进程退出码和退出信号

2301_77509762的博客 5219

【Linux】进程控制 —— 进程创建 | 进程退出 | 进程等待 | 进程程序替换 | 实现简易shell

本文介绍了进程控制相关内容,包括进程创建、退出和等待机制。在进程创建部分,详细讲解了fork函数的实现原理和写时拷贝机制,分析了fork的使用场景和失败原因。进程退出部分阐述了三种退出场景及退出码意义,对比了return、exit和_exit三种退出方式的区别。进程等待部分说明了父进程通过wait/waitpid获取子进程状态的必要性,并演示了wait函数清除僵尸进程的过程。最后指出这些知识有助于理解shell的工作原理,为后续实现简易shell打下基础。

浮光掠影 4047

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

linux进程控制

A.的博客 2700

【linux】linux进程控制(一)(fork进程创建,exit进程终止)

前言 一、进程创建 fork函数 概念讲解 使用for循环同时创建多个进程 写时拷贝 二、进程终止 进程退出场景 代码运行完毕,结果正确或不正确 代码异常终止 总结 进程退出方法 正常退出 return和exit的区别 exit和_exit的区别 异常退出 总结

重铸自身根基的博客 1554

【Linux】进程控制1——进程创建和进程退出

在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。fork之前父进程独立执行,fork之后,父子两个执行流分别执行。注意,fork之后,谁先执行完全由调度器决定。1.将父进程的所有都到了子进程中。(若子进程不对父进程的数据进行修改的话,父子进程的数据也是共享的。若子进程对父进程的数据进行修改时,会发生写时拷贝,将父进程的数据进行一份到子进程中)写时拷贝 :(是一种延时申请技术,可以提高整机内存的使用率)2.

2301_80224556的博客 1320

Linux操作系统2-进程控制1(fork创建子进程,写时拷贝,进程退出)

Linux操作系统fork和进程退出详解

yzc的博客 1240

Linux系统 —— 进程控制系列 - 进程的创建与终止 :fork与exit

Linux系统 —— 进程系列 - 进程的概念,PCB与PID和fork_linux top adbd是什么线程-优快云博客内核写实拷贝,所以以写实拷贝的方式来实现我们父子进程的独立性,这样的话互不干扰。

hedhjd的博客 1502
上一篇: Linux------进程地址空间
下一篇: Linux——进程控制(二)进程等待
kkbca
博客等级 码龄6年 1018粉丝 85原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值