fork源码概要分析

fork属于系统调用,首先从用户态切换到内核态,这个过程前面已经说过了,到了内核态之后就是调用sys_fork(),然后调用do_fork():

asmlinkage int sys_fork(struct pt_regs regs)
{
	return do_fork(SIGCHLD, regs.esp, &regs, 0, NULL, NULL);
}

这个过程会传递一些信号值和寄存器进去。


do_fork功能概要:

1、为子进程分配pid,

2、调用copy_process()函数进行一系列的copy

3、将子进程加入进程调度队列,等待cpu的调度

copy_process()功能概要:

1、为子进程申请一个PCB(task_struct)

调用dup_task_struct()函数,一般分配8k的物理页面,1k用于保存task_struct(PCB),另外一部分用作子进程的内核堆栈

扫描二维码关注公众号,回复: 2544914 查看本文章
	p = dup_task_struct(current);
	if (!p)
		goto fork_out;


2、对PCB进行初始化,如自旋锁,定时器

	INIT_LIST_HEAD(&p->children);
	INIT_LIST_HEAD(&p->sibling);
	p->vfork_done = NULL;
	spin_lock_init(&p->alloc_lock);
	spin_lock_init(&p->proc_lock);

	clear_tsk_thread_flag(p, TIF_SIGPENDING);
	init_sigpending(&p->pending);


3、将父进程的拷贝内存管理mm_struct,文件描述符files,文件系统fs,信号,信号处理函数

if ((retval = copy_semundo(clone_flags, p)))
		goto bad_fork_cleanup_audit;
	if ((retval = copy_files(clone_flags, p)))
		goto bad_fork_cleanup_semundo;
	if ((retval = copy_fs(clone_flags, p)))
		goto bad_fork_cleanup_files;
	if ((retval = copy_sighand(clone_flags, p)))
		goto bad_fork_cleanup_fs;
	if ((retval = copy_signal(clone_flags, p)))
		goto bad_fork_cleanup_sighand;
	if ((retval = copy_mm(clone_flags, p)))
		goto bad_fork_cleanup_signal;
	if ((retval = copy_keys(clone_flags, p)))
		goto bad_fork_cleanup_mm;
	if ((retval = copy_namespace(clone_flags, p)))
		goto bad_fork_cleanup_keys;

这里还对寄存器的值进行了copy和初始化,把eax的值设为0(所以子进程返回值为0),并设置EIP为ret_from_fork的起始地址(子进程从此处开始执行)

retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs);
	if (retval)
		goto bad_fork_cleanup_namespace;


4、调用sched_fork()对子进程的静态优先级初始化,并设置子进程为TASK_RINNING状态

sched_fork(p);



猜你喜欢

转载自blog.csdn.net/crazy_to_imagine/article/details/74897903