当前位置: 首页 > news >正文

【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秒后 exitexit(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 一定是把数据写入缓冲区中,合适的时候,在进行刷新

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

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

相关文章:

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

进程创建 fork 1.fork 之后发生了什么 将给子进程分配新的内存块和内核数据结构&#xff08;形成了新的页表映射&#xff09;将父进程部分数据结构内容拷贝至子进程添加子进程到系统进程列表当中fork 返回&#xff0c;开始调度器调度 这样就可以回答之前返回两个值&#xff1f…...

计算机网络--网络层

一、网络层的服务和功能 网络层主要为应用层提供端对端的数据传输服务 网络层接受运输层的报文段&#xff0c;添加自己的首部&#xff0c;形成网络层分组。分组是网络层的传输单元。网络层分组在各个站点的网络层之间传输&#xff0c;最终到达接收方的网络层。接收方网络层将运…...

【CSS】如何实现分栏布局

在CSS分栏布局中&#xff0c;设置宽度和样式是一个基本且重要的步骤。这可以通过直接应用样式到列元素&#xff08;通常是div元素&#xff09;上来实现。以下是一些常用的方法来设置分栏布局的宽度和样式&#xff1a; 1. 使用百分比宽度 使用百分比宽度可以使列的大小相对于其…...

2025湖北武汉智慧教育装备信息化展/智慧校园展/湖北高博会

2025武汉教育装备展,2025武汉智慧教育展,2025武汉智慧校园展,2025武汉教育信息化展,2025武汉智慧教室展,湖北智慧校园展,湖北智慧教室展,武汉教学设备展,湖北高教会,湖北高博会 2025湖北武汉智慧教育装备信息化展/智慧校园展/湖北高博会 2025第10届武汉国际教育装备及智慧校园…...

Android Studio Run窗口中文乱码解决办法

Android Studio Run窗口中文乱码解决办法 问题描述&#xff1a; AndroidStudio 编译项目时Run窗口中文乱码&#xff0c;如图&#xff1a; 解决方法&#xff1a; 依次打开菜单&#xff1a;Help--Edit Custom VM Options&#xff0c;打开studio64.exe.vmoptions编辑框&#xf…...

代码随想录——划分字母区间(Leetcode763)

题目链接 贪心 class Solution {public List<Integer> partitionLabels(String s) {int[] count new int[27];Arrays.fill(count,0);// 统计元素最后一次出现的位置for(int i 0; i < s.length(); i){count[s.charAt(i) - a] i;}List<Integer> res new Ar…...

SQL注入方法

文章目录 前言如何测试与利用注入点手工注入思路工具sqlmap-r-u-m--level--risk-v-p--threads-batch-smart--os-shell--mobiletamper插件获取数据的相关参数 前言 记录一些注入思路和经常使用的工具&#xff0c;后续有用到新的工具和总结新的方法再继续补充。 如何测试与利用注…...

Vue表单输入绑定v-model

表单输入绑定 在前端处理表单时&#xff0c;我们常常需要将表单输入框的内容同步给Javascript中相应的变量。手动连接绑定和更改事件监听器可能会很麻&#xff0c;v-model 指令帮我们简化了这一步骤。 <template><h3>表单输入绑定</h3><hr> <inpu…...

【分布式系统】ELK 企业级日志分析系统

目录 一.ELK概述 1.简介 1.1.可以添加的其他组件 1.2.filebeat 结合 logstash 带来好处 2.为什么使用ELK 3.完整日志系统基本特征 4.工作原理 二.部署ELK日志分析系统 1.初始化环境 2.完成JAVA部署 三. ELK Elasticsearch 集群部署 1.安装 2.修改配置文件 3.es 性…...

vs2019 无法打开项目文件

vs2019 无法打开项目文件&#xff0c;无法找到 .NET SDK。请检查确保已安装此项且 global.json 中指定的版本(如有)与所安装的版本相匹配 原因&#xff1a;缺少组件 解决方案&#xff1a;选择需要的组件进行安装完成...

Elasticsearch:Painless scripting 语言(一)

Painless 是一种高性能、安全的脚本语言&#xff0c;专为 Elasticsearch 设计。你可以使用 Painless 在 Elasticsearch 支持脚本的任何地方安全地编写内联和存储脚本。 Painless 提供众多功能&#xff0c;这些功能围绕以下核心原则&#xff1a; 安全性&#xff1a;确保集群的…...

SpringBoot项目练习

文章目录 SpringBootVue后台管理系统所需软件下载、安装、版本查询Vue搭建一个简单的Vue项目 Spring项目1项目架构 SpringBootVue后台管理系统 学习视频&#xff1a; https://www.bilibili.com/video/BV1U44y1W77D/?spm_id_from333.337.search-card.all.click&vd_sourcec…...

Android Gradle 开发与应用 (七): Gradle 插件开发与发布

目录 一、概述 二、Gradle插件的基础知识 2.1 Gradle插件的定义 2.2 Gradle插件的种类 2.3 Gradle插件的生命周期 三、开发一个Gradle插件 3.1 创建Gradle插件项目 3.2 编写插件实现 3.3 配置插件元数据 3.4 构建和测试插件 3.5 在项目中应用插件 四、发布Gradle插…...

方法引用详解

什么是方法引用&#xff1f;&#xff1a;针对于函数式接口中的抽象方法 为什么用方法引用&#xff1f;&#xff1a;避免代码的重复&#xff0c;简便书写&#xff0c;提高效率 在使用Lambda表达式的时候&#xff0c;我们实际上传递进去的代码就是一种解决方案&#xff1a;拿参数…...

Apache Seata 高可用部署实践

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Apache Seata 高可用部署实践 Seata 高可用部署实践 使用配置中心和数据库来实现 Seata 的高…...

nginx配置尝试

from fastapi import FastAPI, File, UploadFile, HTTPException from fastapi.responses import JSONResponse, FileResponse, HTMLResponse import logging import os from datetime import datetime import uvicorn# 初始化日志 logging.basicConfig(filenamefile_server.lo…...

SAR目标检测

Multi-Stage with Filter Augmentation 多阶段滤波器增强(MSFA) 对SAR合成孔径雷达目标检测性能的改善 MSFA ON SAR 传统方法: 预训练:传统方法开始于在通用数据集上预训练一个基础模型。 微调:这个预训练的模型会被微调以适应特定的SAR图像&#xff0c;试图缩小域间的差距 …...

创新配置,秒级采集,火爆短视频评论抓取

快速采集评论数据的好处 快速采集评论数据是在当今数字信息时代的市场趋势分析和用户反馈分析中至关重要的环节。通过准确获取并分析大量用户评论&#xff0c;您将能够更好地了解消费者的需求、情感和偏好。集蜂云采集平台提供了一种简单配置的方法&#xff0c;使您能够快速采…...

STL—容器—string类【对其结构和使用的了解】【对oj相关练习的训练】

STL—容器—string类 其实string类准确来说并不是容器&#xff0c;因为他出现的时间比STL要早&#xff0c;但是也可以说是容器吧。 1.为什么要学习string类&#xff1f; 1.1C语言当中的字符串 C语言中&#xff0c;字符串是以’\0’结尾的一些字符的集合&#xff0c;为了操作…...

讲个SystemVerilog随机约束小坑

正文 记录个在写SystemVerilog随机约束时遇到的一个小坑&#xff0c;如果没有认真去查看随机结果是否符合预期&#xff0c;还真不容易发现。 为了方便讲述&#xff0c;写了如下示例代码。类cl_a里有个随机变量aa&#xff0c;初始值为222。在module top里对类cl_a例化并进行约…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架&#xff0c;并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下&#xff0c;重新定义算法中的某些步骤。简单来说&#xff0c;就是在一个方法中定义了要执行的步骤顺序或算法框架&#xff0c;但允许子类…...

Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解

文章目录 一、开启慢查询日志&#xff0c;定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...

在Zenodo下载文件 用到googlecolab googledrive

方法&#xff1a;Figshare/Zenodo上的数据/文件下载不下来&#xff1f;尝试利用Google Colab &#xff1a;https://zhuanlan.zhihu.com/p/1898503078782674027 参考&#xff1a; 通过Colab&谷歌云下载Figshare数据&#xff0c;超级实用&#xff01;&#xff01;&#xff0…...

【版本控制】GitHub Desktop 入门教程与开源协作全流程解析

目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork&#xff08;创建个人副本&#xff09;步骤 2: Clone&#xff08;克隆…...