深入解析 clone():高效的进程与线程创建方法(中英双语)

深入解析 clone():高效的进程与线程创建方法

1. 引言

在 Unix/Linux 系统中,传统的进程创建方式是 fork(),它会复制父进程的地址空间来创建子进程。然而,fork() 复制的资源往往会被 exec() 立即替换,这会导致额外的内存和性能开销

为了解决 fork() 的问题,Linux 提供了 clone(),它是 fork() 的底层实现,同时允许创建共享资源的轻量级进程clone() 也是现代 Linux 容器(如 Docker、LXC)和多线程技术的基础

本文将详细介绍:

  • clone() 解决了什么问题
  • 如何使用 clone()
  • clone() 的内部实现
  • 实际应用场景

2. clone() 解决了什么问题?

2.1 fork() 的性能开销

fork() 进程创建过程中:

  1. 父进程的地址空间被复制,即使采用了写时复制(COW),仍然需要维护页表,带来一定的性能开销。
  2. 如果子进程立即调用 exec(),则复制的内存会被浪费

对于一些特殊的需求,例如:

  • 多线程程序(多个线程共享内存)
  • 容器技术(多个进程共享资源)
  • 高性能服务器(快速创建子进程)

fork() 并不是最优的选择,而 clone() 允许更灵活的进程创建方式


3. clone() 的使用方法

3.1 clone() 的函数原型

#define _GNU_SOURCE
#include <sched.h>
#include <signal.h>int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...);
  • fn:子进程/线程的入口函数,类似于 pthread_create()start_routine
  • child_stack:子进程的栈地址,通常需要手动分配(Linux 5.4+ 可用 CLONE_VM 共享栈)。
  • flags:控制子进程共享哪些资源(如内存、文件描述符等)。
  • arg:传递给 fn 的参数。

3.2 clone() 主要的 flags 选项

Flag描述
CLONE_VM共享内存空间(类似于线程)
CLONE_FS共享文件系统信息
CLONE_FILES共享文件描述符
CLONE_SIGHAND共享信号处理机制
CLONE_THREAD让子进程成为与父进程同一线程组的线程
CLONE_NEWNS创建新的 mount namespace(用于容器)
CLONE_NEWUTS创建新的 UTS namespace(隔离主机名)

4. clone() 的代码示例

4.1 创建轻量级子进程

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>#define STACK_SIZE 1024 * 1024  // 1MB stack sizeint child_func(void *arg) {printf("Child process: PID = %d\n", getpid());return 0;
}int main() {char *stack = malloc(STACK_SIZE);if (!stack) {perror("malloc");exit(EXIT_FAILURE);}pid_t pid = clone(child_func, stack + STACK_SIZE, SIGCHLD, NULL);if (pid == -1) {perror("clone");exit(EXIT_FAILURE);}printf("Parent process: PID = %d, Child PID = %d\n", getpid(), pid);wait(NULL);  // Wait for child process to finishfree(stack);return 0;
}

4.2 解析

  1. 手动分配子进程的栈malloc(STACK_SIZE))。
  2. 调用 clone() 创建子进程
    • SIGCHLD 让子进程在结束时发送 SIGCHLD 信号(类似 fork())。
  3. 父进程等待子进程结束

执行示例

Parent process: PID = 1234, Child PID = 1235
Child process: PID = 1235

5. clone() 在容器中的应用

5.1 clone() 与 Linux Namespace

clone()Linux 容器技术(Docker, LXC)的核心,结合 Namespace,可以隔离文件系统、网络、进程 ID、用户等

示例:创建独立的 UTS 命名空间(隔离主机名)

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>#define STACK_SIZE 1024 * 1024int child_func(void *arg) {sethostname("NewNamespace", 12);  // 修改主机名system("/bin/bash");  // 启动 shellreturn 0;
}int main() {char *stack = malloc(STACK_SIZE);if (!stack) {perror("malloc");exit(EXIT_FAILURE);}pid_t pid = clone(child_func, stack + STACK_SIZE, CLONE_NEWUTS | SIGCHLD, NULL);if (pid == -1) {perror("clone");exit(EXIT_FAILURE);}wait(NULL);free(stack);return 0;
}

执行后

$ hostname
NewNamespace  # 只影响子进程的 UTS Namespace
  • CLONE_NEWUTS 让子进程有自己的主机名,但不影响宿主机。

6. clone() vs fork() vs pthread_create()

方法共享资源适用场景
fork()独立进程(完全复制)标准 Unix 进程创建
clone()可选择共享资源轻量级进程、多线程、容器
pthread_create()线程(共享内存)多线程应用
  • fork() 创建完全独立的进程。
  • clone() 允许共享资源,比 fork() 更高效。
  • pthread_create() clone(CLONE_VM | CLONE_THREAD) 的封装,用于多线程编程。

7. clone() 的实际应用

轻量级多进程服务器

  • 例如 Nginx,可以用 clone() 快速创建共享内存的 worker 进程

Linux 容器技术(Docker, LXC)

  • Docker 使用 clone() + namespace 来实现进程隔离
    • CLONE_NEWNS(隔离文件系统)
    • CLONE_NEWNET(隔离网络)
    • CLONE_NEWUSER(用户映射)

高性能进程管理

  • Chrome 浏览器 使用 clone() 让不同标签页运行在独立的进程,提高安全性。

系统级 API 实现

  • glibcposix_spawn() 在某些 Linux 版本中使用 clone() 作为底层实现

8. 结论

🚀 clone() 提供了比 fork() 更灵活的进程创建方式,适用于多线程、轻量级进程、容器技术。
🚀 现代 Linux 系统的容器(Docker, LXC)、高性能服务器、浏览器沙箱等,都是 clone() 的典型应用。
🚀 理解 clone() 是深入理解 Linux 进程管理和现代系统架构的重要基础!

Deep Dive into clone(): A High-Performance Process and Thread Creation Method

1. Introduction

In Unix/Linux systems, the traditional method for creating processes is fork(), which duplicates the parent process to create a child. However, fork() comes with performance overhead, especially in high-memory applications where even Copy-On-Write (COW) requires page table duplication.

To address this, Linux introduced clone(), which serves as the low-level implementation of fork(), enabling the creation of lightweight processes with shared resources. It is the foundation of modern Linux containers (Docker, LXC) and multi-threading.

This article explores:

  • The problems clone() solves
  • How to use clone()
  • The internal workings of clone()
  • Real-world applications

2. What Problem Does clone() Solve?

2.1 The Performance Overhead of fork()

In a fork()-based process creation:

  1. The parent process’s address space is duplicated.
  2. Even with Copy-On-Write (COW), maintaining page tables adds performance overhead.
  3. If exec() is called immediately after fork(), the copied memory is wasted.

For multi-threading, containerization, and high-performance servers, fork() is suboptimal.

2.2 How clone() Improves Performance

  • Allows sharing resources between parent and child (memory, file descriptors, signal handlers, etc.).
  • Avoids unnecessary memory duplication, reducing overhead.
  • Ideal for multi-threaded applications, container technology, and high-performance computing.

3. How to Use clone()

3.1 Function Prototype

#define _GNU_SOURCE
#include <sched.h>
#include <signal.h>int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...);
  • fn: Entry function for the child process, similar to pthread_create().
  • child_stack: Stack address for the child process (must be manually allocated).
  • flags: Determines which resources are shared between parent and child.
  • arg: Argument passed to fn.

3.2 Key clone() Flags

FlagDescription
CLONE_VMShare memory space (like threads)
CLONE_FSShare file system information
CLONE_FILESShare file descriptors
CLONE_SIGHANDShare signal handlers
CLONE_THREADMake child a thread in the same thread group
CLONE_NEWNSCreate a new mount namespace (for containers)
CLONE_NEWUTSCreate a new UTS namespace (isolates hostname)

4. clone() Code Examples

4.1 Creating a Lightweight Child Process

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>#define STACK_SIZE 1024 * 1024  // 1MB stackint child_func(void *arg) {printf("Child process: PID = %d\n", getpid());return 0;
}int main() {char *stack = malloc(STACK_SIZE);if (!stack) {perror("malloc");exit(EXIT_FAILURE);}pid_t pid = clone(child_func, stack + STACK_SIZE, SIGCHLD, NULL);if (pid == -1) {perror("clone");exit(EXIT_FAILURE);}printf("Parent process: PID = %d, Child PID = %d\n", getpid(), pid);wait(NULL);  // Wait for child processfree(stack);return 0;
}

4.2 Explanation

  1. Manually allocate a stack for the child process (malloc(STACK_SIZE)).
  2. Call clone() to create the child process:
    • SIGCHLD: Ensures the child sends a SIGCHLD signal when it exits (similar to fork()).
  3. Parent waits for the child to complete.

Execution Example:

Parent process: PID = 1234, Child PID = 1235
Child process: PID = 1235

5. clone() in Container Technology

5.1 clone() and Linux Namespaces

clone() is the foundation of Linux container technology (Docker, LXC). Combined with namespaces, it enables process isolation.

Example: Creating a New UTS Namespace (Isolating Hostname)

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>#define STACK_SIZE 1024 * 1024int child_func(void *arg) {sethostname("NewNamespace", 12);  // Change hostnamesystem("/bin/bash");  // Start a shellreturn 0;
}int main() {char *stack = malloc(STACK_SIZE);if (!stack) {perror("malloc");exit(EXIT_FAILURE);}pid_t pid = clone(child_func, stack + STACK_SIZE, CLONE_NEWUTS | SIGCHLD, NULL);if (pid == -1) {perror("clone");exit(EXIT_FAILURE);}wait(NULL);free(stack);return 0;
}

After execution:

$ hostname
NewNamespace  # Affects only the child process UTS namespace
  • CLONE_NEWUTS: Creates an isolated hostname namespace, so changes affect only the child process.

6. clone() vs fork() vs pthread_create()

MethodShared ResourcesUse Case
fork()Independent process (full copy)Standard Unix process creation
clone()Selective resource sharingLightweight processes, multi-threading, containers
pthread_create()Threads (shared memory)Multi-threading applications
  • fork() creates completely separate processes.
  • clone() allows resource sharing, making it faster than fork().
  • pthread_create() is a wrapper around clone(CLONE_VM | CLONE_THREAD), used for multi-threading.

7. Real-World Applications of clone()

Lightweight Multi-Process Servers

  • Example: Nginx can use clone() to create worker processes sharing memory.

Linux Container Technology (Docker, LXC)

  • Docker uses clone() + namespaces to isolate file systems, network, and users:
    • CLONE_NEWNS (Filesystem isolation)
    • CLONE_NEWNET (Network isolation)
    • CLONE_NEWUSER (User ID mapping)

High-Performance Process Management

  • Google Chrome uses clone() to create isolated processes for each tab.

System-Level API Implementations

  • Glibc’s posix_spawn() uses clone() under the hood for efficiency.

8. Conclusion

🚀 clone() provides a more flexible and efficient process creation method, suitable for multi-threading, lightweight processes, and containerization.
🚀 Modern Linux systems, including Docker, LXC, high-performance servers, and web browsers, all rely on clone().
🚀 Understanding clone() is crucial for mastering Linux process management and system architecture!

后记

2025年2月3日于山东日照。在GPT4o大模型辅助下完成。

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

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

相关文章

开屏广告-跳过神器

给大家介绍一款超实用的软件——SKIP&#xff0c;它堪称李跳跳的最佳平替&#xff01;这款软件已经在Github开源免费&#xff0c;完全无需担心内置源问题&#xff0c;也无需导入任何规则。安装完成后&#xff0c;即可直接使用&#xff0c;非常便捷&#xff01; 首次打开软件时…

大模型本地化部署(Ollama + Open-WebUI)

文章目录 环境准备下载Ollama模型下载下载Open-WebUI 本地化部署的Web图形化界面本地模型联网查询安装 Docker安装 SearXNG本地模型联网查询 环境准备 下载Ollama 下载地址&#xff1a;Ollama网址 安装完成后&#xff0c;命令行里执行命令 ollama -v查看是否安装成功。安装成…

自制虚拟机(C/C++)(三、做成标准GUI Windows软件,扩展指令集,直接支持img软盘)

开源地址:VMwork 要使终端不弹出&#xff0c; #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") 还要实现jmp near 0x01类似的 本次的main.cpp #include <graphics.h> #include <conio.h> #include <windows.h> #includ…

【游戏设计原理】97 - 空间感知

一、游戏空间的类型 将游戏设计中的空间设计单独提取出来&#xff0c;可以根据其结构、功能和玩家的交互方式划分为以下几种主要类型。这些类型可以单独存在&#xff0c;也可以组合使用&#xff0c;以创造更加复杂和有趣的游戏体验。 1. 线性空间 定义&#xff1a;空间设计是…

基于开源AI智能名片2 + 1链动模式S2B2C商城小程序视角下的个人IP人设构建研究

摘要&#xff1a;本文深入探讨在开源AI智能名片2 1链动模式S2B2C商城小程序的应用场景下&#xff0c;个人IP人设构建的理论与实践。通过剖析个人IP人设定义中的“诉求”“特质”“可感知”三要素&#xff0c;结合该小程序特点&#xff0c;阐述其对个人IP打造的影响与推动作用&…

数据库和数据表的创建、修改、与删除

1.标识符命名规则 数据库名、表名不得超过30个字符&#xff0c;变量名限制为29个 必须只能包含A-Z,a-z,0-9,_共63个字符 数据库名、表名、字段名等对象名中间不能包含空格 同一个MySQL软件中&#xff0c;数据库不能同名&#xff1b;同一个库中&#xff0c;表不能重名&#…

算法日记10:SC62求和(单调栈)(共享求解)

一、题目 二、题解&#xff1a; 1、首先&#xff0c;我们看到题目的第一个想法&#xff0c;就是把样例答案如何求解给列出来&#xff0c;图例如下 2、通过分析样例&#xff0c;可以很清晰的发现每一个数字都有其管辖的区间&#xff0c;因此我们可以想到能否找到一个数字它所管…

Revit二次开发 自适应族添加放样融合

大多数博客给出的方案都是如何在有自适应族的情况下进行修改定位点或是将数据传入自适应族,如何直接在族文件中创建自适应模型并将点转换为自适应点,连接自适应点成为自适应路径这种方式没有文章介绍. 下面的代码中给出了如何在自适应族文件中创建参照点并转换为自适应点连接…

基于VMware的ubuntu与vscode建立ssh连接

1.首先安装openssh服务 sudo apt update sudo apt install openssh-server -y 2.启动并检查ssh服务状态 到这里可以按q退出 之后输入命令 &#xff1a; ip a 红色挡住的部分就是我们要的地址&#xff0c;这里就不展示了哈 3.配置vscode 打开vscode 搜索并安装&#xff1a;…

解决SetWindowCompositionAttribute使控件文本透明的问题

用以下参数调用该API&#xff0c;能实现类似Aero的模糊透明效果。 参数具体含义见 https://zhuanlan.zhihu.com/p/569258181 http://www.memotech.de/WindowComposition/Text.txt http://www.memotech.de/WindowComposition/WindowComposition.zip DWORD accent[4] { 3,0,0,0 …

使用 DeepSeek-R1 与 AnythingLLM 搭建本地知识库

一、下载地址Download Ollama on macOS 官方网站&#xff1a;Ollama 官方模型库&#xff1a;library 二、模型库搜索 deepseek r1 deepseek-r1:1.5b 私有化部署deepseek&#xff0c;模型库搜索 deepseek r1 运行cmd复制命令&#xff1a;ollama run deepseek-r1:1.5b 私有化…

SQL入门到精通 理论+实战 -- 在 MySQL 中学习SQL语言

目录 一、环境准备 1、MySQL 8.0 和 Navicat 下载安装 2、准备好的表和数据文件&#xff1a; 二、SQL语言简述 1、数据库基础概念 2、什么是SQL 3、SQL的分类 4、SQL通用语法 三、DDL&#xff08;Data Definition Language&#xff09;&#xff1a;数据定义语言 1、操…

Java篇之继承

目录 一. 继承 1. 为什么需要继承 2. 继承的概念 3. 继承的语法 4. 访问父类成员 4.1 子类中访问父类的成员变量 4.2 子类中访问父类的成员方法 5. super关键字 6. super和this关键字 7. 子类构造方法 8. 代码块的执行顺序 9. protected访问修饰限定符 10. 继承方式…

使用SpringBoot发送邮件|解决了部署时连接超时的bug|网易163|2025

使用SpringBoot发送邮件 文章目录 使用SpringBoot发送邮件1. 获取网易邮箱服务的授权码2. 初始化项目maven部分web部分 3. 发送邮件填写配置EmailSendService [已解决]部署时连接超时附&#xff1a;Docker脚本Dockerfile创建镜像启动容器 1. 获取网易邮箱服务的授权码 温馨提示…

TensorFlow简单的线性回归任务

如何使用 TensorFlow 和 Keras 创建、训练并进行预测 1. 数据准备与预处理 2. 构建模型 3. 编译模型 4. 训练模型 5. 评估模型 6. 模型应用与预测 7. 保存与加载模型 8.完整代码 1. 数据准备与预处理 我们将使用一个简单的线性回归问题&#xff0c;其中输入特征 x 和标…

vue入门到实战 三

目录 3.1 v-bind 3.1.1 v-bind指令用法 ​编辑3.1.2 使用v-bind绑定class 3.1.3 使用v-bind绑定style 3.2.1 v-if指令 3.2.1 v-if指令 3.2.2 v-show指令 ​3.3 列表渲染指令v-for 3.3.1 基本用法 3.3.2 数组更新 3.3.3 过滤与排序 3.4 事件处理 3.4.1 使用v-on指令…

《苍穹外卖》项目学习记录-Day10订单状态定时处理

利用Cron表达式生成器生成Cron表达式 1.处理超时订单 查询订单表把超时的订单查询出来&#xff0c;也就是订单的状态为待付款&#xff0c;下单的时间已经超过了15分钟。 //select * from orders where status ? and order_time < (当前时间 - 15分钟) 遍历集合把数据库…

解决MacOS安装软件时提示“打不开xxx软件,因为Apple无法检查其是否包含恶意软件”的问题

macOS 系统中如何开启“任何来源”以解决安装报错问题&#xff1f; 大家好&#xff01;今天我们来聊聊在使用 macOS 系统 时&#xff0c;遇到安装应用软件时出现报错的情况。这种情况常常发生在安装一些来自第三方开发者的应用时&#xff0c;因为 macOS 会默认阻止不明开发者的…

【FreeRTOS 教程 六】二进制信号量与计数信号量

目录 一、FreeRTOS 二进制信号量&#xff1a; &#xff08;1&#xff09;二进制信号量作用&#xff1a; &#xff08;2&#xff09;二进制信号量与互斥锁的区别&#xff1a; &#xff08;3&#xff09;信号量阻塞时间&#xff1a; &#xff08;4&#xff09;信号量的获取与…

C++模板编程——可变参函数模板之折叠表达式

目录 1. 什么是折叠表达式 2. 一元左折 3. 一元右折 4. 二元左折 5. 二元右折 6. 后记 上一节主要讲解了可变参函数模板和参数包展开&#xff0c;这一节主要讲一下折叠表达式。 1. 什么是折叠表达式 折叠表达式是C17中引入的概念&#xff0c;引入折叠表达式的目的是为了…