【Linux】进程创建和终止 | slab分配器

进程创建 fork

1.fork 之后发生了什么

  1. 将给子进程分配新的内存块和内核数据结构(形成了新的页表映射)
  2. 将父进程部分数据结构内容拷贝至子进程
  3. 添加子进程到系统进程列表当中
  4. fork 返回,开始调度器调度

这样就可以回答之前返回两个值?

发生了写实拷贝,形成了两个物理空间块

测试

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

int main(void)
{
    printf("Before -> pid: %d\n", getpid());
    fork();
    printf("After -> pid: %d\n", getpid());

    sleep(1);

    return 0;
}

创建了一个子进程

一般来说子进程创建之后,会共享父进程的所有代码

是怎么知道的呢?没关系,eip 程序计数器会出手!

eip 叫做 程序计数器,用来保存当前正在执行的指令的下一条指令。eip 程序计数器会拷贝给子进程,子进程便从该 eip 所指向的代码处开始执行。

我们再来重新思考一下 fork 之后操作系统会做什么:

" 进程 = 进程的数据结构 + 进程的代码和数据 "

创建子进程的内核数据结构:

(struct task_struct + struct mm_struct + 页表)+ 代码继承父进程,数据以写时拷贝的方式来进行共享或者独立。

代码共享,写实拷贝确保了进程的独立性

写实拷贝

当任意一方试图写入,就会按照写时拷贝的方式各自拷贝一份副本出来。写时拷贝本身由操作系统的内存管理模块完成的。

选择暂时先不给你,等你什么时候要用什么时候再给。这就变相的提高了内存的使用情况。

fork

fork 之后利用 if-else 进行分流, 让父子执行不同的代码块。我们做网络写服务器的时候会经常采用这样的编码方式,例如父进程等待客户端请求,生成子进程来处理请求。

继承大纲后又有所区别

fork 肯定不是永远都成功的,fork 也是有可能调用失败的。

测试

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

int main(void)
{
    for (;;) {//写了一个死循环
        pid_t id = fork();
        if (id < 0) {
            printf("子进程创建失败!\n");
            break;
        }
        if (id == 0) {
            printf("I am a child... %d\n", getpid());
            sleep(2); // 给它活2秒后 exit
            exit(0);  // 成功就退出
        }
    }

    return 0;
}


进程终止 exit

为什么要使用return?

思考:代码运行完的结果一般有以下三种:

代码运行完毕,结果正确

代码运行完毕,结果不正确

代码异常中止

成功了就是成功了,失败了就会有各种原因

我们重点来对不正确进行思考

  • 进程中,谁会关心我运行的情况呢? 父进程

怎么表示不同的出错原因呢?

A: 进程的退出码

  • return 0 表示正确
  • main函数的返回值本质:表示进程运行完成时,是否是正确的结果,如果不是,我们可以用不同的数字表示出错的原因

模拟一个逻辑的实现

$? : 保存的是最近的一次进程退出的时候的退出码

我们想要进步,不再是随便无脑 return 了,我该怎么办呢?

一般而言,失败的非零值我该如何设置呢?非零值默认表达的含义又是什么呢?

首先,失败的非零值是可以自定义的,我们可以看看系统对于不同数字默认的 错误码 是什么含义。C 语言当中有个的 string.h 中有一个 strerror 接口

如果感兴趣可以看看 2.6.32 的内核代码中的 /usr/include/asm-generic/errno.h 及 errno-base.h,输出错误原因定义归纳整理如下:

#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */

查看错误码 strerror(i)

我们可以在 Linux 下写个程式去把这些错误码给打印出来:

结果如下:

系统提供的错误码和

添加图片

const char *errString[]={
"success",
"error 1",
"error 2",
"error 3"
};

实践:

对于 ls myfile.txt 的查看

  • $?: 2

其中,0 表示 success,1 表示权限不允许,2 找不到文件或目录。

我们刚才 ls 一个不存在的,再 echo $? 显示对应的错误码就是 2:

所以无论正确还是不正确,统一会采用进程的退出码来进行判定

不同的错误码,方便我们定位问题出在哪里

我们可以通过以下方法来查看

C 语言中 errno - number of last error

打印错误 strerror(errno)

?:如果代码异常了,退出码还有意义吗?

本质可能就是代码没有跑完,都跑不到那个地方了

进程的退出码无意义了,因为可能都到不了 return

? : 那么如何知道发生了什么异常呢? 发信号

eg. 野指针

举例 8 11 表示异常

kill -8 出现野指针 -11 段错误


终止进程的做法:

#include<stdlib.h>

exit 的退出码 12

exit 在任意地方被调用,都表示调用进程直接退出

return 只表示当前函数的返回

测试

#include <stdio.h>
#include <stdlib.h>
 
void func() {
    printf("hello func\n");
    exit(111);
}
 
int main(void)
{
    func();    
 
    return 10;
}

注意,只有在 main 函数调 return 才叫做 进程退出,其他函数调 return 叫做 函数返回

_exit 和 exit

exit 会清理缓冲区,关闭流等操作,而 _exit 什么都不干,直接终止。

void func() {
    printf("hello exit");
    exit(0);
}
 
int main(void)
{
    func();    
    printf("hello _exit");
    _exit(0);
}

是否冲刷缓冲区的区别

缓冲区(Buffer)的概念在计算机科学中非常广泛,但在你提供的上下文中,缓冲区指的是一种用于临时存储数据的内存区域。在介绍内核的数据结构缓冲池时,缓冲区的概念主要与提升性能和合理利用内存资源有关。

具体来说,你提供的描述强调了以下几点:

  1. 开辟空间和初始化有成本
    • 在操作系统中,每次为新进程或新数据结构开辟内存空间并初始化都需要花费时间和资源,这会影响系统性能。
  1. 废弃的数据结构链表
    • 为了优化这种开销,Linux 操作系统会维护一张废弃的数据结构链表。这个链表上存放的是那些已经被标记为“无效”的数据结构,但其内存空间并没有被立即释放。这些数据结构包括 task_structmm_struct 等。
  1. 重用策略
    • 当一个进程被释放(即终止)后,它的相关数据结构不会立即被完全删除,而是被标记为无效并加入废弃的数据结构链表中。
    • 当有新的进程创建时,操作系统会首先检查这个链表,从中取出一个合适的、已经存在的但无效的数据结构(如 task_structmm_struct),进行必要的初始化然后再使用。
  1. 内核的数据结构缓冲池
    • 这种方法本质上是一种内存池,也即“缓冲池”,专门用来存放和重用数据结构的内存。
    • Slab 分配器(Slab Allocator)即是实现这种内存池概念的机制之一。通过使用 slab 分配器,系统能有效减少重复的内存分配和释放操作,提高运行效率,并减少内存碎片化的问题。

它的原理是将内存按照大小分成不同的块,然后将这些块以页的形式进行分配和管理。当需要分配内存时,slab 分配器会从对应大小的块中选择一个可用的块分配给程序,当内存不需要时,这块内存又会被返回到对应的块中以便后续重复使用,从而降低了内存的分配和释放开销。这种方式可以提高内存分配的性能,减少内存碎片化

sum:
缓冲区在这个背景下的概念是指一块预分配的内存,用来存储和重复利用特定类型的数据结构。这种做法可以显著减少频繁的内存分配和释放所带来的开销,提高系统性能,这也是 slab 分配器背后的核心思想。

slab 分配器:根据合适的内存拿,不要就放回去

我们 printf 一定是把数据写入缓冲区中,合适的时候,在进行刷新

这个缓冲区绝对不在哪里?

绝对不在内核里,在用户空间,要不然一定会被刷新

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

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

相关文章

线程池理解及7个参数

定义理解 线程池其实是一种池化的技术实现&#xff0c;池化技术的核心思想就是实现资源的复用&#xff0c;避免资源的重复创建和销毁带来的性能开销。线程池可以管理一堆线程&#xff0c;让线程执行完任务之后不进行销毁&#xff0c;而是继续去处理其它线程已经提交的任务。 …

web缓存代理服务器

一、web缓存代理 web代理的工作机制 代理服务器是一个位于客户端和原始&#xff08;资源&#xff09;服务器之间的服务器&#xff0c;为了从原始服务器取得内容&#xff0c;客户端向代理服务器发送一个请求&#xff0c;并指定目标原始服务器&#xff0c;然后代理服务器向原始…

【IT领域新生必看】 Java编程中的重载(Overloading):初学者轻松掌握的全方位指南

文章目录 引言什么是方法重载&#xff08;Overloading&#xff09;&#xff1f;方法重载的基本示例 方法重载的规则1. 参数列表必须不同示例&#xff1a; 2. 返回类型可以相同也可以不同示例&#xff1a; 3. 访问修饰符可以相同也可以不同示例&#xff1a; 4. 可以抛出不同的异…

【踩坑】解决undetected-chromedriver报错cannot connect to-chrome

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 网上方法都试了&#xff0c;什么指定version_main、添加option等。 最终&#xff0c;放弃&#xff0c;直接换selenium自己的吧&#xff1a; from web…

【论文解读】LivePortrait:具有拼接和重定向控制的高效肖像动画

&#x1f4dc; 文献卡 英文题目: LivePortrait: Efficient Portrait Animation with Stitching and Retargeting Control;作者: Jianzhu Guo; Dingyun Zhang; Xiaoqiang Liu; Zhizhou Zhong; Yuan Zhang; Pengfei Wan; Di ZhangDOI: 10.48550/arXiv.2407.03168摘要翻译: *旨在…

IDEA配Git

目录 前言 1.创建Git仓库&#xff0c;获得可提交渠道 2.选择本地提交的项目名 3.配置远程仓库的地址 4.新增远程仓库地址 5.开始进行commit操作 6.push由于邮箱问题被拒绝的解决方法&#xff1a; 后记 前言 以下操作都是基于你已经下载了Git的前提下进行的&#xff0c…

基于机器学习(支持向量机,孤立森林,鲁棒协方差与层次聚类)的机械振动信号异常检测算法(MATLAB 2021B)

机械设备异常检测方法流程一般如下所示。 首先利用传感器采集机械运行过程中的状态信息&#xff0c;包括&#xff0c;振动、声音、压力、温度等。然后采用合适的信号处理技术对采集到机械信号进行分析处理&#xff0c;提取能够准确反映机械运行状态的特征。最后采用合理的异常决…

算法系列--分治排序|再谈快速排序|快速排序的优化|快速选择算法

前言:本文就前期学习快速排序算法的一些疑惑点进行详细解答,并且给出基础快速排序算法的优化版本 一.再谈快速排序 快速排序算法的核心是分治思想,分治策略分为以下三步: 分解:将原问题分解为若干相似,规模较小的子问题解决:如果子问题规模较小,直接解决;否则递归解决子问题合…

Debezium报错处理系列之第110篇: ERROR Error during binlog processing.Access denied

Debezium报错处理系列之第110篇:ERROR Error during binlog processing. Last offset stored = null, binlog reader near position = /4 Access denied; you need at least one of the REPLICATION SLAVE privilege for this operation 一、完整报错二、错误原因三、解决方法…

智能化客户服务:提升效率与体验的新模式

在数字化浪潮的推动下&#xff0c;客户服务领域正经历着一场深刻的变革。智能化客户服务的兴起&#xff0c;不仅重塑了企业与客户之间的互动方式&#xff0c;更在提升服务效率与增强客户体验方面展现出了巨大潜力。本文将深入探讨智能化客户服务的新模式&#xff0c;分析其如何…

Error in onLoad hook: “SyntaxError: Unexpected token u in JSON at position 0“

1.接收页面报错 Error in onLoad hook: "SyntaxError: Unexpected token u in JSON at position 0" Unexpected token u in JSON at position 0 at JSON.parse (<anonymous>) 2.发送页面 &#xff0c;JSON.stringify(item) &#xff0c;将对象转换为 JSO…

InspireFace-商用级的跨平台开源人脸分析SDK

InspireFace-商用级的跨平台开源人脸分析SDK InspireFaceSDK是由insightface开发的⼀款⼈脸识别软件开发⼯具包&#xff08;SDK&#xff09;。它提供了⼀系列功能&#xff0c;可以满⾜各种应⽤场景下的⼈脸识别需求&#xff0c;包括但不限于闸机、⼈脸⻔禁、⼈脸验证等。 该S…

运维锅总详解CPU

本文从CPU简介、衡量CPU性能指标、单核及多核CPU工作流程、如何平衡 CPU 性能和防止CPU过载、为什么计算密集型任务要选择高频率CPU、超线程技术、CPU历史演进及摩尔定律等方面对CPU进行详细分析。希望对您有所帮助&#xff01; 一、CPU简介 CPU&#xff08;中央处理器&#…

2024年马蹄杯专科组第三场初赛 解题报告 | 珂学家

前言 题解 VP了这场比赛&#xff0c;整体还是偏简单&#xff0c;最难的题是数论相关&#xff0c;算一道思维题。 也看了赛时榜单&#xff0c;除了数论&#xff0c;大模拟和图论题也是拦路虎。 打工人 有趣的一道数学题&#xff0c;有点绕 很像数列和 ∑ i 1 i n i n ∗ …

14-20 Vision Transformer用AI的画笔描绘新世界

概述 毫无疑问,目前最受关注且不断发展的最重要的主题之一是使用人工智能生成图像、视频和文本。大型语言模型 (LLM) 已展示出其在文本生成方面的卓越能力。它们在文本生成方面的许多问题已得到解决。然而,LLM 面临的一个主要挑战是它们有时会产生幻觉反应。 最近推出的新模…

06-6.4.5 关键路径

&#x1f44b; Hi, I’m Beast Cheng &#x1f440; I’m interested in photography, hiking, landscape… &#x1f331; I’m currently learning python, javascript, kotlin… &#x1f4eb; How to reach me --> 458290771qq.com 喜欢《数据结构》部分笔记的小伙伴可以…

Apispec,一个用于生成 OpenAPI(Swagger)规范的 Python 库

目录 01什么是 Apispec&#xff1f; 为什么选择 Apispec&#xff1f; 安装与配置 02Apispec 的基本用法 生成简单的 API 文档 1、创建 Apispec 实例 2、定义 API 路由和视图 3、添加路径到 Apispec 集成 Flask 和 Apispec 1、安装…

Buuctf之SimpleRev做法

首先&#xff0c;查个壳&#xff0c;64bit&#xff0c;那就丢进ida64中进行反编译进来之后&#xff0c;我们进入main函数&#xff0c;发现里面没什么东西&#xff0c;那就shiftf12搜索字符串&#xff0c;找到关键字符串&#xff0c;双击进入然后再选中该字符串&#xff0c;ctrl…

东莞惠州数据中心机房搬迁方案流程

进入21世纪以来&#xff0c;数据中心如雨后春笋般在各行各业兴建起来&#xff0c;经过近20年的投产运行&#xff0c;大量的数据中心机房存在容量不足、机房陈旧、设备老化无法支撑业务发展的情况&#xff0c;产生机房改造、搬迁需求。为安全、可靠地完成机房搬迁&#xff0c;减…

【JVM 的内存模型】

1. JVM内存模型 下图为JVM内存结构模型&#xff1a; 两种执行方式&#xff1a; 解释执行&#xff1a;JVM是由C语言编写的&#xff0c;其中有C解释器&#xff0c;负责先将Java语言解释翻译为C语言。缺点是经过一次JVM翻译&#xff0c;速度慢一点。JIT执行&#xff1a;JIT编译器…