Create a file test-fork.c:
#include <unistd.h>
int main (void)
{
fork();
return 0;
}
Compile it with static binding: gcc -O0 -static -Wall test-fork.c -o test-fork
Disassemble it: objdump -D -S test-fork > test-fork.dis
Open the file test-fork.disand search fork:
fork();
80481f4: e8 63 55 00 00 call 804d75c <__libc_fork>
return 0;
80481f9: b8 00 00 00 00 mov $0x0,%eax
}
80481fe: c9 leave
80481ff: c3 ret
Then do a search __libc_fork:
0804d75c <__libc_fork>:
804d75c: 55 push %ebp
804d75d: b8 00 00 00 00 mov $0x0,%eax
804d762: 89 e5 mov %esp,%ebp
804d764: 53 push %ebx
804d765: 83 ec 04 sub $0x4,%esp
804d768: 85 c0 test %eax,%eax
804d76a: 74 12 je 804d77e <__libc_fork+0x22>
804d76c: c7 04 24 80 e0 0a 08 movl $0x80ae080,(%esp)
804d773: e8 88 28 fb f7 call 0 <_init-0x80480d4>
804d778: 83 c4 04 add $0x4,%esp
804d77b: 5b pop %ebx
804d77c: 5d pop %ebp
804d77d: c3 ret
804d77e: b8 02 00 00 00 mov $0x2,%eax
804d783: cd 80 int $0x80
804d785: 3d 00 f0 ff ff cmp $0xfffff000,%eax
804d78a: 89 c3 mov %eax,%ebx
804d78c: 77 08 ja 804d796 <__libc_fork+0x3a>
804d78e: 89 d8 mov %ebx,%eax
804d790: 83 c4 04 add $0x4,%esp
804d793: 5b pop %ebx
804d794: 5d pop %ebp
804d795: c3 ret
Please note that on this particular hardware / core forkis associated with syscall number 2
Download a copy of the Linux kernel: wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.23.tar.bz2
Open file linux-2.6.23/arch/x86/kernel/syscall_table_32.S
Please note that syscall 2 is associated with
sys_fork:
.long sys\_fork
Open file linux-2.6.23/arch/x86/kernel/process.c
Find sys_fork:
asmlinkage int sys_fork(struct pt_regs regs)
{
return do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL);
}
Note that it do_fork()is called only with the parameterSIGCHLD
Open the file linux-2.6.23/kernel/fork.c. It is determined here do_fork()!
do_fork()then calls copy_process():
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);
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)) {
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;
}
forking do_fork(),
kernel/fork.c. , do_fork():
- PID ,
alloc_pid() ptrace (.. current->ptrace)copy_process(), ,
- ,
do_fork() PID - , ,
clone_flags - ,
security_task_create() security_task_alloc() dup_task_struct(), , thread_info task_struct .
alloc_task_struct() task_struct tsk.alloc_thread_info thread_info titask_struct, tsk, tsk->thread_info tithread_info , ti, ti->task tsk- (..
tsk->usage) 2, , , ( EXIT_ZOMBIE EXIT_DEAD) - (..
tsk)
copy_process() , (.. , `max_threads)
- ,
task_struct copy_flags() flags task_struct
PF_SUPERPRIV ( , ) PF_NOFREEZEPF_FORKNOEXEC ( , `exec()) โโ- `init_sigpending(),
- ,
do_fork(), copy_process() `, sched_fork(),- ,
do_fork() SIGSTOP , CLONE_STOPPED (.. PT_PTRACED p->ptrace)
CLONE_STOPPED , wake_up_new_task(), :
- ,
- , , (..
CLONE_VM ), , runqueue . , . , . - , , , (.
CLONE_VM), runqueue
- ,
CLONE_STOPPED, TASK_STOPPED , PID
ptrace_message current
ptrace_notify(), SIGCHLD . "" - , ; SIGCHLD , , PID , current->ptrace_message.
CLONE_VFORK, , ( , )
- PID .