在讲进程管理专题最核心的课题——进程创建之前,我们先简单地回顾一下上一篇博文的sys_clone()系统调用:
asmlinkage int sys_clone(struct pt_regs regs)
{
unsigned long clone_flags;
unsigned long newsp;
int __user *parent_tidptr, *child_tidptr;
clone_flags = regs.ebx;
newsp = regs.ecx;
parent_tidptr = (int __user *)regs.edx;
child_tidptr = (int __user *)regs.edi;
if (!newsp)
newsp = regs.esp;
return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr);
}
那么,在同一个文件中(针对80x86平台是/arch/i386/kernel/Process.c),有:
asmlinkage int sys_fork(struct pt_regs regs)
{
return do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL);
}
asmlinkage int sys_vfork(struct pt_regs regs)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL);
}
我们看到,不管是clone、fork还是vfork系统调用,他们的实现函数sys_clone、sys_fork和sys_vfork都指向了位于/kernel/Fork.c中的do_fork函数,唯一的不同就是clone_flags的不同,具体含义请参考前一博文。
这里,我们就来详细分析进程创建的实务函数 —— do_fork()
long do_fork(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr)
先介绍一下它执行时使用的参数:
clone_flags:与clone()参数flags相同。
stack_start:与clone()参数stack_start相同。
regs:指向内核态堆栈通用寄存器值的指针,通用寄存器的值是在从用户态切换到内核态时被保存到内核态堆栈中的。
stack_size:未使用,总被设置为0。
parent_tidptr,child_tidptr:与clone系统调用中对应参数ptid和ctid相同。
do_fork()函数利用辅助函数copy_process()来创建进程描述符以及子进程所需要的其他所有数据结构。下面是do_fork()函数执行的主要步骤:
1. 通过查找pidmap_array位图,为子进程
进程的创建 —— do_fork()函数详解
最新推荐文章于 2023-03-27 16:01:21 发布
本文详细剖析了Linux内核中的do_fork函数,它是进程创建的核心,涉及分配PID、检查跟踪、复制进程描述符、设置状态等步骤。do_fork调用copy_process创建进程数据结构,并通过一系列操作准备子进程的执行,包括信号处理、资源分配、权限复制等。在do_fork之后,子进程虽然完整,但尚未实际运行,需要由调度程序决定何时执行。
摘要由CSDN通过智能技术生成