参考文章:
版权声明:本文为CSDN博主「HZero.chen」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:blog.csdn.net/jasonaction…
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:blog.csdn.net/m0_50662680…
fork/vfork/clone/kthread/kernel_clone
kernel_clone
是底层的内核函数,用于实现进程和线程的创建操作。fork
、vfork
、clone
和 kthread
都是与之相关的高级函数或系统调用,通过调用 kernel_clone
来创建新的进程或线程,但在具体的参数设置和行为上略有差异
fork
函数原型:
#include
pid_t fork(void);
vfork
函数原型:
#include
pid_t vfork(void);
clone
函数原型:
#define _GNU_SOURCE
#include
int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...);
kthread_create
函数原型:
#include
struct task_struct *kthread_create(int (*threadfn)(void *data),
void *data,
const char *namefmt,
...);
kernel_clone
函数原型:
struct kernel_clone_args {
u64 flags;
int __user *pidfd;
int __user *child_tid;
int __user *parent_tid;
int exit_signal;
unsigned long stack;
unsigned long stack_size;
unsigned long tls;
pid_t *set_tid;
/* Number of elements in *set_tid */
size_t set_tid_size;
int cgroup;
struct cgroup *cgrp;
struct css_set *cset;
};
pid_t kernel_clone(struct kernel_clone_args* args);
stack
: 只在创建线程时有意义, 用来指定线程的用户栈的地址
stack_size
:只在创建线程时有意义, 用来指定线程的用户栈的大小
flags
: clone 标志
CLONE_VM
: 共享进程地址空间CLONE_FS
: 共享文件系统信息CLONE_FILES
: 共享打开文件描述符表CLONE_NOFILES
: 子进程不共享打开文件描述符表CLONE_SIGHAND
: 共享信号处理程序CLONE_PID
: 新进程与父进程拥有相同的进程 ID (PID)CLONE_PIDFD
: 共享 pidfd 文件描述符表CLONE_PTRACE
: 允许父进程对子进程进行跟踪CLONE_VFORK
: 子进程处于 vfork 状态CLONE_VFORKDONE
: 等待 vfork 子进程完成CLONE_PARENT
: 子进程的父进程被设置为与调用fork
的进程相同CLONE_THREAD
: 创建一个线程而不是独立进程CLONE_SYSVSEM
: 共享 System V 信号量CLONE_SETTLS
: 设置新进程的 TLS (Thread Local Storage)CLONE_UNTRACED
: 对子进程进行跟踪,但不报告其停止状态CLONE_RESTART
: 如果父进程在等待期间被信号中断,则重新启动子进程CLONE_PARENT_SETTID
: 将子进程设置为父进程中的字段 TID(用于获取新创建线程的线程 ID)CLONE_CHILD_CLEARTID
: 在子进程退出时清除子进程中的字段 TIDCLONE_CHILD_SETTID
: 将子进程设置为子进程中的字段 TID(用于获取线程 ID)CLONE_CHILD_STOPPED
: 在创建子进程后将其暂停CLONE_NEWNS
: 创建一个新的挂载命名空间CLONE_NEWPIDFD
: 创建一个新的 pidfd 命名空间CLONE_NEWUTS
: 创建一个新的 UTS 命名空间CLONE_NEWIPC
: 创建一个新的 IPC 命名空间CLONE_NEWUSER
: 创建一个新的用户命名空间CLONE_NEWPID
: 创建一个新的 PID 命名空间CLONE_NEWNET
: 创建一个新的网络命名空间CLONE_IO
: 新进程共享 I/O 上下文CLONE_NEWCGROUP
: 创建一个新的 cgroup 命名空间CLONE_NEWTIME
: 创建一个新的时间命名空间
进程和线程
Linux内核中没有定义真正意义上的线程,不论用户态还是内核态的进程/线程,都是由kernel_clone内核函数所创建的可调度的执行流。
内核进程
内核进程(kernel process)是在操作系统内核中运行的特殊进程。与普通用户进程不同,内核进程直接运行在内核态,具有更高的特权级别和访问权限。
内核进程在操作系统的运行中扮演着重要的角色,负责执行和管理内核级任务,包括但不限于以下功能:
内核进程运行在内核空间,拥有直接访问和操作内核数据结构和系统资源的能力。由于其特权级别较高,内核进程对系统的稳定性和安全性非常重要。
内核进程是由操作系统的内核自身创建的。在操作系统启动时,内核会初始化并创建一些必要的内核进程,这些进程负责执行核心的操作系统功能和服务。
具体地说,内核进程的创建通常发生在操作系统的启动阶段,它们可以包括但不限于以下几个常见的内核进程:
这些内核进程的创建一般是作为操作系统启动的一部分,由内核自身负责管理和维护。内核进程的数量和具体功能可能因不同的操作系统而有所不同。
内核进程是由操作系统的内核自身创建的。在操作系统启动时,内核会初始化并创建一些必要的内核进程,这些进程负责执行核心的操作系统功能和服务。
具体地说,内核进程的创建通常发生在操作系统的启动阶段,它们可以包括但不限于以下几个常见的内核进程:
内核线程
Linux内核线程是在操作系统内核中运行的一种特殊类型的线程。与用户空间的进程不同,内核线程没有独立的地址空间和用户权限,它们运行在内核模式下,并且可以直接访问操作系统的数据结构和核心功能。
kthreadd(内核线程管理器, PID=2)是Linux内核中的一个特殊进程,它是所有其他内核线程的创建者和管理者。kthreadd是在内核启动时由主线程启动的第一个内核线程。
kthreadd具有以下功能:
通过kthreadd的存在,可以有效管理内核线程的创建与销毁,并且能够避免频繁地创建和销毁内核线程所带来的性能开销。它在Linux内核中扮演着重要的角色,确保内核线程的有效运行和管理。
用户进程
在 Linux 系统中,用户进程是指由用户创建并运行的进程。用户进程是与用户交互、执行应用程序或服务的主要组成部分。
当用户登录到 Linux 系统时,系统为每个用户分配一个用户空间,用户可以在该空间中创建和运行自己的进程。这些进程通常是通过终端、图形界面或远程连接启动的。
用户进程可以是各种类型的应用程序,比如文本编辑器、图形界面程序、网络服务器、脚本等。它们执行各种任务,满足用户的需求,实现各种功能。
在 Linux 中,用户进程的 PID(进程号)通常大于 1,因为 1 号进程是 init 进程或其他类似的系统级进程。用户进程会与其他进程相互作用,共享系统资源,并由操作系统的调度器对其进行管理和调度。
用户线程
linux内核中未实现真正意义的线程,而是采用轻量进程作为用户态线程的载体。linux用户线程通常是Posix线程,采用pthread库以及libc中的NTPL(Native POSIX Thread Library),最终调用clone()系统调用函数创建。称之为轻量级进程(LWP, light weight process)。
clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL
| CLONE_SETTLS | CLONE_PARENT_SETTID
| CLONE_CHILD_CLEARTID | CLONE_SYSVSEM
| 0);
golang GMP 中的 M
M在linux下就是调用clone()系统调用创建的Posix线程。