【linux】进程创建,进程终止

news2025/1/11 23:57:10

进程创建,进程终止

  • 1.进程创建
    • 1.1写时拷贝
    • 1.2fork常规用法
    • 1.3fork调用失败的原因
  • 2.进程终止
    • 2.1退出码
    • 2.2进程退出场景
    • 2.3进程如何退出

1.进程创建

在前面创建子进程的时候就学过了fork函数,它能从已经存在进程中创建一个新进程,新进程为子进程,而原进程为父进程。

当进程调用fork,当控制转移到内核中的fork代码后,内核做:

分配新的内存块和内核数据结构给子进程
将父进程部分数据结构内容拷贝至子进程
添加子进程到系统进程列表当中
fork返回,开始调度器调度

在这里插入图片描述fork之前父进程独立执行,fork之后,父子两个执行流分别执行。注意,fork之后,谁先执行完全由调度器决定。

1.1写时拷贝

通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。具体见下图
在这里插入图片描述
写时拷贝在进程地址空间详细讲述了,这里不再细说。

这里主要讲解fork返回值的问题。

1.如何理解fork返回之后,给父进程返回子进程的pid,给子进程返回0。

父亲:孩子-----> 1:n的关系。
一个父亲有一个或者n个孩子,如果想找到某个孩子,必须知道孩子的名字。
孩子有且只有以恶搞父亲,想要找父亲的时候,有操作系统提供的getppid()。

2.如何理解fork函数有两个返回值问题。

在这里插入图片描述
当一个函数准备return的时候,核心代码已经执行完了,所以子进程早已经创建好了,并且可能在OS运行队列中,准备被调度了。
前面所说父子进程共享fork之后的代码,其实不准确,在fork函数之内父子进程就已经分流共享了,所以父子进程各自执行return。

3.如何理解同一个id值,怎么可能保存两个不同的值。让if else同时执行

pid_t id = fork();返回的本质就是写入,所以谁先返回,谁就先写入id,因为进程具有独立性,所以写时拷贝,因此同一个id,地址是一样,但是内容是不一样。

1.2fork常规用法

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

后面再程序替换具体讲exec函数。

1.3fork调用失败的原因

系统中有太多的进程
实际用户的进程数超过了限制

这是一段一直创建子进程的代码,等到不能创建子进程了就退出,会看见创建子进程个数。

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

int main()
{
    int cnt = 0;
    while(1)
    {
        int ret = fork();
        if(ret < 0){
            printf("fork error!, cnt: %d\n", cnt);
            break;
        }
        else if(ret == 0){
            //child
            while(1) sleep(1);
        }
        //partent
        cnt++;
    }
    return 0;
}

2.进程终止

2.1退出码

int main()
{
	//...
	return 0;
}

通常main函数最后都要有一句return 0;其实这是进程退出的时候,对应的退出码,标定进程执行的结果是否正确。

#include<stdio.h>                                                                                                            
#include<string.h>                                                                                                           
                                                                                                                                                                                                                                                      
int AddtoTarget(int from,int end)                                                                                            
{                                                                                                                            
     int sum=0;                                                                                                               
     for(int i=from;i<end;++i)                                                                                                
     {                                                                                                                        
         sum+=i;                                                                                                              
     }                                                                                                                        
     return sum;                                                                                                              
 }                                                                                                                            
                                                                                                                              
int main()                                                                                                                   
{                                                                                                                            
                                                                                                                                                                                                                                                 
     //写代码是为了完成某件事情,我们如何得知事情完成的怎么样呢?
     //进程退出码                                                                                                                                                 
     int num=AddtoTarget(1,100);
     if(num == 5050)       
         return 0;         
     else                                                                                                                       
         return 1;                                                                                                        
     return 0;             
 }  
echo $? //查看进程退出码

$? 该符号永远记录最近一个进程在命令行中执行完毕时对应的退出码。

在这里插入图片描述
这里下面显示0是怎么回事呢?

这是因为echo 也是一个子进程,因此剩下的三个的是echo &?是一个echo子进程的退出码。

既然知道退出码。那如何设定main函数的返回值呢?
如果不关心进程退出码,return 0就行。
如果未来我们要关心进程退出码的时候,要返回特定的数据表明特定的错误。

退出码的意义: 0 标识success , !0 标识失败,!0具体是几,标识不同的错误。
但是数字对人不友好,对计算机友好。

所以一般而言,退出码都必须有对应退出码的文字描述
1.可以自定义
2.可以使用系统的映射关系

C库给我们提供一个函数,查看进程退出码对应的信息
在这里插入图片描述

#include<stdio.h>
#include<string.h>

int main()
{
    for(int i=0;i<200;++i)
    {
       printf("%d: %s\n",i,strerror(i));                                                                                                                         
    } 
     return 0;
 }

在这里插入图片描述
strerror记录了对应的退出码的映射信息,总共135个,这里截取了一小部分。

2.2进程退出场景

1.代码跑完,结果正确--------return 0;
2.代码跑完,结果不正确--------return !0;
3.代码没跑完,程序异常了,退出码无意义;(比如野指针,越界等等)

2.3进程如何退出

1.main函数return返回,其他函数return是调用结束。

2.任意地方调用exit。
在这里插入图片描述

  1 #include<stdio.h>  
  2 #include<string.h>  
  3 #include<unistd.h>  
  4 #include<stdlib.h>
  5 int AddtoTarget(int from,int end)
  6 {
  7     int sum=0;
  8     for(int i=from;i<=end;++i)
  9     {
 10         sum+=i;                                                                                                                                                  
 11     }  
 12     exit(12);  
 13    // return sum;  
 14 }  
 15   
 16 int main()  
 17 {  
 18     int ret=AddtoTarget(1,100);  
 19     if(ret == 5050)  
 20         return 0;  
 21     else  
 22         return 1;  
 23 }

在这里插入图片描述

3._exit(了解)
在这里插入图片描述

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<unistd.h>
  4 #include<stdlib.h>
  5 int AddtoTarget(int from,int end)
  6 {
  7     int sum=0;
  8     for(int i=from;i<=end;++i)
  9     {
 10         sum+=i;
 11     }
 12    // exit(12);
 13    _exit(12);                                                                                                                                                    
 14    // return sum;
 15 }
 16 
 17 int main()
 18 {
 19     int ret=AddtoTarget(1,100);
 20     if(ret == 5050)                                                                       
 21         return 0;                                    
 22     else                                   
 23         return 1; 
 24 }

在这里插入图片描述
对比exit和_exit发现,都可以使进程再任意地方结束。
exit是库函数,_exit是系统调用。
库函数在系统调用上面。(操作系统哪里画过图)
再看一段代码

int main()
{
     printf("hello linux");
     sleep(2);
     exit(1);
}

在这里插入图片描述

int main()
{
     printf("hello linux");
     sleep(2);
     _exit(1);
}

在这里插入图片描述
对比发现,exit会刷新缓存区,而_exit并不会刷新缓存区。
这里要说明的是exit会调用_exit。
在这里插入图片描述
问缓冲区在哪?
如果在内存,exit调用_exit去终止进程,exit/_exit都应该会刷新缓冲区。
所以缓冲区在用户空间,是用户级的缓冲区

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

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

相关文章

Python 图形化界面基础篇:打开和关闭新窗口

Python 图形化界面基础篇&#xff1a;打开和关闭新窗口 引言 Tkinter 库简介步骤1&#xff1a;导入 Tkinter 模块步骤2&#xff1a;创建 Tkinter 窗口步骤3&#xff1a;创建一个新窗口步骤4&#xff1a;关闭新窗口步骤5&#xff1a;启动 Tkinter 主事件循环 完整示例代码代码解…

C语言指针详解(4)———找工作必看指针笔试题汇总

指针对于编程工作的重要性 C语言指针在找工作中具有重要性。以下是几个原因&#xff1a; 1.高效的内存管理&#xff1a;C语言指针可以帮助程序员高效地管理内存&#xff0c;包括动态内存分配和释放&#xff0c;以及数据的访问和操作。这对于开发性能优化的应用程序非常重要&am…

7.代理模式

1.UML 2.代码 #include <iostream> using namespace std;class Subject{ public:virtual void Request() 0; };class RealSubject:public Subject { public:virtual void Request(){cout << "RealSubject" << endl;} }; class Proxy:public Subj…

VUE build:gulp打包:测试、正式环境

目录 项目结构 Gulp VUE使用Gulp Vue安装Gulp Vue定义Gulp.js package.json build文件夹 config文件夹 static-config文件夹 项目结构 Gulp Gulp是一个自动化构建工具&#xff0c;可以帮助前端开发者通过自动化任务来管理工作流程。Gulp使用Node.js的代码编写&#xff…

go初识iris框架(五) -MVC包的使用

在Iris框架中&#xff0c;封装了mvc包作为对mvc架构的支持&#xff0c;方便开发者遵循mvc的开发原则进行开发。 iis框架支持请求数据、模型、持久数据分层处理&#xff0c;并支持各层级模块代码绑定执行。 MVC即&#xff1a;model、view、controller三个部分&#xff0c;分别代…

【微信小程序】swiper的使用

1.swiper的基本使用 <jxz-header></jxz-header> <view class"banner"><swiperprevious-margin"30rpx"autoplayinterval"2000"indicator-dotsindicator-color"rgba(0,0,0,0.3)"indicator-active-color"#bda…

数字化管理平台建设实践

在勘察设计行业&#xff0c;各企业加速推进数字化转型。通过管理要素数字化&#xff0c;不断优化内部组织运营效率&#xff1b;通过生产手段数字化、技术产品数字化&#xff0c;提升服务质量&#xff0c;改善客户体验&#xff1b;通过数字化营销&#xff0c;精准对接市场需求&a…

Linux下的系统编程——信号(十一)

前言&#xff1a; 信号在我们的生活中随处可见&#xff0c; 如&#xff1a;古代战争中摔杯为号&#xff1b;现代战争中的信号弹&#xff1b;体育比赛中使用的信号枪...... 他们都有共性&#xff0c;信号是信息的载体&#xff0c;Linux/UNIX 环境下&#xff0c;古老、经典的通信…

基于Java+SpringBoot+Vue的图书借还小程序的设计与实现(亮点:多角色、点赞评论、借书还书、在线支付)

图书借还管理小程序 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序&#xff08;小蔡coding&#xff09;2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 主要功能描述 五、系统实现5.1 小…

.NET 8 Release Candidate 1 (RC1)现已发布,包括许多针对ASP.NET Core的重要改进!

这是我们计划在今年晚些时候发布的最终.NET 8版本之前的两个候选版本中的第一个。大部分计划中的功能和变更都包含在这个候选版本中&#xff0c;可以供您尝试使用。您可以在文档中找到完整的ASP.NET Core在.NET 8中的新功能列表。一些领域&#xff08;尤其是Blazor&#xff09;…

SpringMvc第六战-【SpringMvcJSON返回异常处理机制】

前言&#xff1a; 小编讲述了&#xff1a;JSR303的概念&#xff0c;应用场景和在具体实例的使用&#xff1b;和拦截器的应用 今天小编来讲述的为cJSON返回&异常处理机制&#xff0c;json返回就不用多说&#xff0c;毕竟大部分数据都是通过Json来传递数据的&#xff0c;异…

elasticsearch4-文档操作

个人名片&#xff1a; 博主&#xff1a;酒徒ᝰ. 个人简介&#xff1a;沉醉在酒中&#xff0c;借着一股酒劲&#xff0c;去拼搏一个未来。 本篇励志&#xff1a;三人行&#xff0c;必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》&#xff0c;SpringCloud…

VSCode 安装使用教程 环境安装配置 保姆级教程

一个好用的 IDE 不仅能提升我们的开发效率&#xff0c;还能让我们保持愉悦的心情&#xff0c;这样才是非常 Nice 的状态 ^_^ 那么&#xff0c;什么是 IDE 呢 &#xff1f; what IDE&#xff08;Integrated Development Environment&#xff0c;集成开发环境&#xff09;是含代码…

Python实现四维图像绘制系统

文章目录 动图绘制系统的实现播放控制接口优化总结 Python绘图系统&#xff1a; 源码地址&#xff1a;Python打造动态绘图系统&#x1f4c8;从0开始的3D绘图系统&#x1f4c9;一套3D坐标&#xff0c;多个函数&#x1f4ca;散点图、极坐标和子图自定义控件&#xff1a;绘图风格…

Modbus协议介绍及Modbus TCP

这里写目录标题 一、Modbus起源1.起源2.分类3.优势4.应用场景5.ModbusTCP特点⭐⭐⭐ 二、Modbus TCP协议格式1.报文头2.寄存器3.功能码4.协议包书写模板总结 一、Modbus起源 1.起源 Modbus由Modicon公司于1979年开发&#xff0c;是一种工业现场总线协议标准。 Modbus通信协议…

网络存储解决方案:选择与配置

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

03MyBatis-Plus中的常用注解

常用注解 TableName MyBatis-Plus根据BaseMapper中指定的泛型(实体类型名)确定数据库中操作的表,如果根据实体类型名找不到数据库中对应的表则会报表不存在异常 //向表中插入一条数据 Test public void testInsert(){User user new User(null, "张三", 23, "…

基于Java+SpringBoot+Vue+uniapp点餐小程序(亮点:协同过滤算法、会员系统,购物车结算、在线聊天)

校园点餐小程序 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序&#xff08;小蔡coding&#xff09;2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 系统功能结构设计4.2 主要功能描述 五…

【操作系统】深入浅出死锁问题

死锁的概念 在多线程编程中&#xff0c;我们为了防止多线程竞争共享资源而导致数据错乱&#xff0c;都会在操作共享资源而导致数据错乱&#xff0c;都会在操作共享资源之前加上互斥锁&#xff0c;只有成功获得到锁的线程&#xff0c;才能操作共享资源&#xff0c;获取不到锁的…

Python新手入门

文章目录 概要python代码运行结果小结 概要 以下内容为python各种输出语句的语法&#xff01; python代码 # 标准化输出 print("这是标准化输出&#xff01;")# 格式化输出 print("这是第1种%s"%"格式化输出&#xff01;") print("这是第…