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

news2025/2/24 16:29:25

进程创建 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 一定是把数据写入缓冲区中,合适的时候,在进行刷新

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

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

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

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

相关文章

Autosar Dcm配置-0x85服务配置及使用-基于ETAS软件

文章目录 前言Dcm配置DcmDsdDcmDsp代码实现总结前言 0x85服务用来控制DTC设置的开启和关闭。某OEM3.0架构强制支持0x85服务,本文介绍ETAS工具中的配置 Dcm配置 DcmDsd 配置0x85服务 此处配置只在扩展会话下支持(具体需要根据需求决定),两个子服务Disable为0x02,Enable…

3.pwn 函数调用流程,调用约定

前置准备 pop: Pop指令的作用是弹栈&#xff0c;将栈顶的数据弹出到寄存器&#xff0c;然后栈顶指针向下移动一个单位。 具体来说:如pop rax&#xff0c;作用就是mov rax[rsp];add rsp 8; push: Push指令的作用就是压栈&#xff0c;将栈顶指针向上移动一个单位的距离&#xf…

38 IO流

目录 C语言的输入和输出流是什么CIO流stringstream的简单介绍 1. C语言的输入与输出 C语言中我们用到的最频繁的输出方式是scanf和printf&#xff0c;scanf&#xff1a;从标准输入设备&#xff08;键盘&#xff09;读取数据&#xff0c;并将值存在变量中。printf&#xff1a;…

【MySQL】锁(黑马课程)

【MySQL】锁 0. 锁的考察点1. 概述1. 锁的分类1.1 属性分类1.2 粒度分类 2. 全局锁2.1 全局锁操作2.2.1 备份问题 3. 表级锁3.1 表锁3.2 语法3.3 表共享读锁&#xff08;读锁&#xff09;3.4 表独占写锁&#xff08;写锁&#xff09;3.5 元数据锁(meta data lock, MDL)3.6 意向…

第5章 认证授权:需求分析,Security介绍(OAuth2,JWT),用户认证,微信扫码登录,用户授权

1 模块需求分析 1.1 什么是认证授权 截至目前&#xff0c;项目已经完成了课程发布功能&#xff0c;课程发布后用户通过在线学习页面点播视频进行学习。如何去记录学生的学习过程呢&#xff1f;要想掌握学生的学习情况就需要知道用户的身份信息&#xff0c;记录哪个用户在什么…

AIGC专栏12——EasyAnimateV3发布详解 支持图文生视频 最大支持960x960x144帧视频生成

AIGC专栏12——EasyAnimateV3发布详解 支持图&文生视频 最大支持960x960x144帧视频生成 学习前言项目特点生成效果相关地址汇总项目主页Huggingface体验地址Modelscope体验地址源码下载地址 EasyAnimate V3详解技术储备Diffusion Transformer (DiT)Hybrid Motion ModuleU-V…

智慧校园-教职工管理系统总体概述

在当今信息化时代&#xff0c;智慧校园教职工管理系统成为了提升教育机构管理效能的重要工具。该系统巧妙融合了先进的信息技术&#xff0c;为教职工的日常管理带来了一场静悄悄的革命。它不仅是一个信息存储库&#xff0c;记录着每位教职工从加入到离开的完整职业轨迹&#xf…

笔记12:if语句编程练习(打印输出三个数据中的最小值)

输入三个数&#xff0c;分别放入变量x&#xff0c;y&#xff0c;z中 打印输入数据中最小的那一个数 解决方案1 定义中间变量 t 1.比较x和y的大小关系&#xff0c;将较小的值赋值给t 2.比较t和z的大小关系&#xff0c;将较小的值赋值给t 3.t 中保存的就是3个数中的较小值 &am…

限时免费!国产Sora快手可灵Web网页端及全新功能上线!国货之光!

大家好&#xff0c;我是程序员X小鹿&#xff0c;前互联网大厂程序员&#xff0c;自由职业2年&#xff0c;也一名 AIGC 爱好者&#xff0c;持续分享更多前沿的「AI 工具」和「AI副业玩法」&#xff0c;欢迎一起交流~ 快手可灵&#xff08;Kling&#xff09;这回是真的出息了&…

Python爬取股票信息-并进行数据可视化分析,绘股票成交量柱状图

为了使用Python爬取股票信息并进行数据可视化分析&#xff0c;我们可以使用几个流行的库&#xff1a;requests 用于网络请求&#xff0c;pandas 用于数据处理&#xff0c;以及 matplotlib 或 seaborn 用于数据可视化。 步骤 1: 安装必要的库 首先&#xff0c;确保安装了以下P…

Hack The Box -- Blazorized

一、准备工作 端口扫描 详细扫描 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-30 21:39 EDT Nmap scan report for 10.10.11.22 Host is up (0.26s latency).PORT STATE SERVICE VERSION 53/tcp open domain Simple DNS Plus 80/tcp op…

海外发稿: 秘鲁-区块链新闻媒体通稿宣发

秘鲁媒体单发 随着全球化的不断深入&#xff0c;海外发稿已经成为众多企业宣传推广的重要方式之一。而在海外发稿的选择中&#xff0c;秘鲁媒体的地位尤为重要。秘鲁作为南美洲的重要国家之一&#xff0c;拥有众多知名媒体平台&#xff0c;包括diariodelcusco、serperuano、el…

非堆成加密是公私钥使用

对称加密学习-CSDN博客 加密算法学习-CSDN博客 非对称加密算法使用一对密钥&#xff0c;包括一个公钥和一个私钥&#xff0c;它们是数学上相关联的&#xff0c;但公钥可以公开分享&#xff0c;而私钥必须保密。以下是使用非对称加密算法的一般步骤&#xff1a; 密钥生成&…

【IT领域新生必看】深入浅出Java:揭秘`Comparator`与`Comparable`的神奇区别

文章目录 引言什么是Comparable接口&#xff1f;Comparable接口的定义实现Comparable接口示例&#xff1a; 什么是Comparator接口&#xff1f;Comparator接口的定义实现Comparator接口示例&#xff1a; Comparable与Comparator的区别排序逻辑位置示例&#xff1a; 可扩展性示例…

HashMap中的put()方法

一. HashMap底层结构 HashMap底层是由哈希表(数组),链表,红黑树构成,哈希表存储的类型是一个节点类型,哈希表默认长度为16,它不会每个位置都用,当哈希表中的元素个数大于等于负载因子(0.75)*哈希表长度就会扩容到原来的2倍 二. 底层的一些常量 三. HashMap的put()方法 当插入一…

简单的手动实现spring中的自动装配案例

简简单单的实现一个spring中的自动装配和容器管理的小骚操作。 1&#xff0c;创建AutoSetBean.java 使用injectBeans静态方法&#xff0c;可以扫描指定包下的所有带MyInject注解的字段&#xff0c;如果在beans的Map中存在这个字段的实例化类&#xff0c;则执行装配。 import…

c语言题目:成绩管理系统

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

Windows系统下载安装ngnix

一 nginx下载安装 nginx是HTTP服务器和反向代理服务器&#xff0c;功能非常丰富&#xff0c;在nginx官网首页&#xff0c;点击download 在download页面下&#xff0c;可以选择Stable version稳定版本&#xff0c;点击下载 将下载完成的zip解压即可&#xff0c;然乎在nginx所在…

【MySQL】事务四大特性以及实现原理

事务四大特性 原子性&#xff08;Atomicity&#xff09; 事务中的所有操作要么全部完成&#xff0c;要么全部不执行。如果事务中的任何一步失败&#xff0c;整个事务都会被回滚&#xff0c;以保持数据的完整性。 一致性&#xff08;Consistency&#xff09; 事务应确保数据库…

集智书童 | 英伟达和斯坦福基于 Transformer 的异常检测最新研究!

本文来源公众号“集智书童”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;英伟达和斯坦福基于 Transformer 的异常检测最新研究&#xff01; 在作者推动各种视觉任务性能边界的同时&#xff0c;模型的大小也在相应增长。为了跟上…