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

细说fork-vfork-pthread_create-clone

1.1 fork

特点

  • 完全复制父进程的地址空间
  • 父子进程独立运行
  • 返回两次(父进程返回子进程PID,子进程返回0)
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main() {pid_t pid = fork();if (pid < 0) {perror("fork failed");return 1;} else if (pid == 0) {// 子进程printf("Child process (PID: %d)\n", getpid());} else {// 父进程printf("Parent process (PID: %d), Child PID: %d\n", getpid(), pid);}return 0;
}
输出:
Parent process (PID: 413843), Child PID: 413844
Child process (PID: 413844)

1.2 vfork

特点

  • 子进程与父进程共享地址空间
  • 子进程必须先调用exec或_exit
  • 比fork()更高效

示例

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main() {pid_t pid = vfork();if (pid < 0) {perror("vfork failed");return 1;} else if (pid == 0) {// 子进程printf("Child process (PID: %d)\n", getpid());_exit(0); // 必须使用_exit而不是exit} else {// 父进程printf("Parent process (PID: %d), Child PID: %d\n", getpid(), pid);}return 0;
}

1.3 pthread_create

特点

  • 创建新线程而非进程
  • 共享同一进程的地址空间
  • 需要链接pthread库(-lpthread)

示例:

#include <stdio.h>
#include <pthread.h>void* thread_func(void* arg) {printf("New thread created\n");return NULL;
}int main() {pthread_t tid;int ret = pthread_create(&tid, NULL, thread_func, NULL);if (ret != 0) {perror("pthread_create failed");return 1;}printf("Main thread\n");pthread_join(tid, NULL); // 等待线程结束return 0;
}

1.4 clone

特点

  • 可以精细控制共享哪些资源
  • 功能最强大但也最复杂
  • 通常用于实现线程库

示例

#define _GNU_SOURCE
#include <stdio.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>#define STACK_SIZE (1024 * 1024)static int child_func(void* arg) {printf("Child process (PID: %d)\n", getpid());return 0;
}int main() {char* stack = malloc(STACK_SIZE);if (!stack) {perror("malloc failed");return 1;}// 创建子进程,共享虚拟内存、文件描述符等pid_t pid = clone(child_func, stack + STACK_SIZE, CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_SIGHAND, NULL);if (pid < 0) {perror("clone failed");free(stack);return 1;}printf("Parent process (PID: %d), Child PID: %d\n", getpid(), pid);waitpid(pid, NULL, 0); // 等待子进程结束free(stack);return 0;
}

1.5 内核视角看

  1. 所有任务创建最终都调用do_fork()(内核函数)
  2. clone()是最接近do_fork()的用户空间接口
  3. 其他函数都是clone()的包装:
    • fork()clone(SIGCHLD)
    • vfork()clone(CLONE_VFORK | CLONE_VM | SIGCHLD)
    • 线程 ≈ clone(共享大部分资源的flags)

1.6 总结

特性fork()vfork()pthread_create()clone()
创建对象进程进程线程轻量级进程/线程
地址空间复制共享共享可配置
执行顺序不确定子进程先运行不确定可配置
资源开销可配置
使用复杂度简单中等中等
主要用途通用进程创建exec前创建进程多线程编程高级线程/进程控制

选择哪种方法取决于具体需求:需要完全隔离用fork,需要快速exec用vfork,需要共享数据用线程,需要精细控制用clone。


http://www.mrgr.cn/news/100613.html

相关文章:

  • 【dify+docker安装教程】
  • 八大排序——冒泡排序/归并排序
  • 【云计算】云计算中IaaS、PaaS、SaaS介绍
  • 安卓基础(点击项目)
  • 高能效计算:破解算力增长与能源约束的科技密码
  • 夜莺监控V8(Nightingale)二进制部署教程(保姆级)
  • 微分与积分(前言)
  • WPF之Label控件详解
  • VUE3:封装一个评论回复组件
  • 1.7无穷级数
  • Uniapp(vue):生命周期
  • InitializingBean接口和@PostConstruct-笔记
  • SpringBoot启动后自动执行方法的各种方式-笔记
  • 【亚马逊云】AWS Wavelength 从理论讲解到实验演练
  • 在 cmd shell 中执行 metasploit vbs payload
  • 项目实战-贪吃蛇大作战【补档】
  • 数据库安装和升级和双主配置
  • Java读Excel:解析阿里云easyExcel导入文件的行号
  • 人物5_My roommate
  • yolov8+kalman 实现目标跟踪统计人流量