Linux内核是如何创建一个新进程的?
作者:网络转载 发布时间:[ 2016/5/17 10:17:29 ] 推荐标签:操作系统 Linux
sched_fork 流程
core.c
int sched_fork(unsigned long clone_flags, struct task_struct *p)
{
unsigned long flags;
int cpu = get_cpu();
__sched_fork(clone_flags, p);
//将子进程状态设置为 TASK_RUNNING
p->state = TASK_RUNNING;
//……
//为子进程分配 CPU
set_task_cpu(p, cpu);
put_cpu();
return 0;
}
我们可以看到sched_fork大致完成了两项重要工作,一是将子进程状态设置为 TASK_RUNNING,二是为其分配 CPU
copy_thread 流程
int copy_thread(unsigned long clone_flags, unsigned long sp,
unsigned long arg, struct task_struct *p)
{
//获取寄存器信息
struct pt_regs *childregs = task_pt_regs(p);
struct task_struct *tsk;
int err;
p->thread.sp = (unsigned long) childregs;
p->thread.sp0 = (unsigned long) (childregs+1);
memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
if (unlikely(p->flags & PF_KTHREAD)) {
//内核线程
memset(childregs, 0, sizeof(struct pt_regs));
p->thread.ip = (unsigned long) ret_from_kernel_thread;
task_user_gs(p) = __KERNEL_STACK_CANARY;
childregs->ds = __USER_DS;
childregs->es = __USER_DS;
childregs->fs = __KERNEL_PERCPU;
childregs->bx = sp; /* function */
childregs->bp = arg;
childregs->orig_ax = -1;
childregs->cs = __KERNEL_CS | get_kernel_rpl();
childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_FIXED;
p->thread.io_bitmap_ptr = NULL;
return 0;
}
//将当前寄存器信息复制给子进程
*childregs = *current_pt_regs();
//子进程 eax 置 0,因此fork 在子进程返回0
childregs->ax = 0;
if (sp)
childregs->sp = sp;
//子进程ip 设置为ret_from_fork,因此子进程从ret_from_fork开始执行
p->thread.ip = (unsigned long) ret_from_fork;
//……
return err;
}
copy_thread 这段代码为我们解释了两个相当重要的问题!
一是,为什么 fork 在子进程中返回0,原因是childregs->ax = 0;这段代码将子进程的 eax 赋值为0
二是,p->thread.ip = (unsigned long) ret_from_fork;将子进程的 ip 设置为 ret_form_fork 的首地址,因此子进程是从 ret_from_fork 开始执行的
总结
新进程的执行源于以下前提:
dup_task_struct中为其分配了新的堆栈
调用了sched_fork,将其置为TASK_RUNNING
copy_thread中将父进程的寄存器上下文复制给子进程,保证了父子进程的堆栈信息是一致的
将ret_from_fork的地址设置为eip寄存器的值
终子进程从ret_from_fork开始执行
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
Linux下开源的DDR压力测试工具曝Linux恶意软件:让树莓派设备挖掘数字货币linux系统中不同颜色的文件夹及根目录介绍软件测试工程师必知必会Linux命令Linux下DNS服务器配置如何成为不可替代的Linux运维工程师?详解Linux进程(作业)的查看和杀死Linux 日志定时轮询流程详解比特币勒索病毒不只Windows系统有,Linux版的来了Linux日志定时轮询流程详解Linux iommu和vfio概念空间解构Linux系统如何低于TCP洪水攻击Linux无损调整分区大小Linux下防火墙配置实例Linux使用Jexus托管Asp.Net Core应用程序Linux中引号的那些事
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南