推荐内容
Linux2.6内核进程创建过程分析
/*Kernel version: linux-2.6.22.9
*作者:旋木木
*日期:2007/10/17
*E-mail:xuanmumu@gmail.com
*/
Fork的系统调用代码在linux/arch/i386/kernel/process.c中:
asmlinkage int sys_fork(struct pt_regs regs)
{
return do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL);
}
Sys_fork系统调用通过 do_fork()函数实现,通过对do_fork()函数传递不同的clone_flags来实现fork,clone,vfork。
Syn_clone和syn_vfork的系统调用代码如下:
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);
}
asmlinkage int sys_vfork(struct pt_regs regs)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL);
}
其中clone_flas在include\linux\sched.h中定义
/*
* cloning flags:
*/
#define CSIGNAL 0x000000ff /* 进程退出时需要传递的信号*/
#define CLONE_VM 0x00000100 /* 父子进程共享地址空间 */
#define CLONE_FS 0x00000200 /* 父子进程共享文件系统信息 */
#define CLONE_FILES 0x00000400 /* 父子进程共享已打开的文件 */
#define CLONE_SIGHAND 0x00000800 /* 父子进程共享信号处理 */
#define CLONE_PTRACE 0x00002000 /* 继续调试子进程 */
#define CLONE_VFORK 0x00004000 /* 调用vfork(),父进程休眠*/
#define CLONE_PARENT 0x00008000 /* 设置一个共有的父进程 */
#define CLONE_THREAD 0x00010000 /* 父子进程在同一个线程组 */
#define CLONE_NEWNS 0x00020000 /* 为子进程创建一个新的命名空间 */
#define CLONE_SYSVSEM 0x00040000 /* 父子进程共享system V SEM_UNDO */
#define CLONE_SETTLS 0x00080000 /* 为子进程创建新的TLS */
#define CLONE_PARENT_SETTID 0x00100000 /* 设置父进程TID */
#define CLONE_CHILD_CLEARTID 0x00200000 /* 清除子进程TID */
#define CLONE_DETACHED 0x00400000 /* Unused, ignored */
#define CLONE_UNTRACED 0x00800000 /* 不允许调试子进程 */
#define CLONE_CHILD_SETTID 0x01000000 /* 设置子进程TID */
#define CLONE_STOPPED 0x02000000 /* 设置进程停止状态 */
#define CLONE_NEWUTS 0x04000000 /* 创建新的utsname组 */
#define CLONE_NEWIPC 0x08000000 /* 创建新的IPC */
Do_fork()在kernel/fork.c中定义,代码如下:
/*
* Ok, this is the main fork-routine.
*
* It copies the process, and if successful kick-starts
* it and waits for it to finish using the VM if required.
*/
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)
{
struct task_struct *p;
int trace = 0;
struct pid *pid = alloc_pid();
long nr;
if (!pid)
return -EAGAIN;
nr = pid->nr;
if (unlikely(current->ptrace)) {
trace = fork_traceflag (clone_flags);
if (trace)
clone_flags |= CLONE_PTRACE;
}
p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);
/*
* Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly.
*/
if (!IS_ERR(p)) {
struct completion vfork;
if (clone_flags & CLONE_VFORK) {
p->vfork_done = &vfork;
init_completion(&vfork);
}
if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)) {
/*
* We'll start up with an immediate SIGSTOP.
*/
sigaddset(&p->pending.signal, SIGSTOP);
set_tsk_thread_flag(p, TIF_SIGPENDING);
}
if (!(clone_flags & CLONE_STOPPED))
wake_up_new_task(p, clone_flags);
else
p->state = TASK_STOPPED;
if (unlikely (trace)) {
current->ptrace_message = nr;
ptrace_notify ((trace << 8) | SIGTRAP);
}
if (clone_flags & CLONE_VFORK) {
freezer_do_not_count();
wait_for_completion(&vfork);
freezer_count();
if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) {
current->ptrace_message = nr;
ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
}
}
} else {
free_pid(pid);
nr = PTR_ERR(p);
}
return nr;
}
Do_fork()函数的核心是copy_process()函数,该函数完成了进程创建的绝大部分工作并且也在fork.c定义,copy_process函数较长,逐段往下看:







评论列表