linux下C语言fork(),LinuxC语言:fork()、vfork()及clone()

[转载]fork()、vfork()及clone()

fork()、vfork()和clone()分别通过系统INT

0X80调用sys_fork()、sys_vfork()或sys_clone(),从下面的

代码可以看出,它们都调用了do_fork(),唯一的区别是所传参数中clone_flags不同。

fork():建立一个新的process

vfork():建立一个新的process,并且父进程阻塞,直到子进程SIG或exit.(与此相对的是copy

on write技术)

clone():用于建立一个LWT()

写个简单的程序来看。

test.c

[back@Test back]$ cat test.c

//======================================================================

// Illustrate fork() &&

vfork() by

jie.hong

//======================================================================

#include

#include

#include

int main()

{

int i = -1;

int j = -1;

i = vfork();

j = fork();

printf("\nThe PID is [%d],[%d]\n", i,j);

return 0;

}

[back@Test back]$ gcc test.c -o test

[back@Test back]$ ./test

The PID is

[0],[29304] //29303打印

The PID is

[29303],[29305] //29302打印

Segmentation fault

[back@Test back]$

The PID is

[29303],[0] //29305打印

The PID is

[0],[0] //29304打印

初始PID为29302,vfork后其阻塞,其子进程(29303)执行fork()产生29304

,而29302结束阻塞

后则fork()产生29305如下图.

vfork() fork() 29302------------->29303-------------->29304

|

|

|fork()

|

|

29305

关键区别为clone_flag不同。

[back@Test back]$ gdb test

GNU gdb Red Hat Linux (5.3.90-0.20030710.41.2.1rh)

Copyright 2003 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License,

and you are

welcome to change it and/or distribute copies of it under certain

conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB. Type

"show warranty" for details.

This GDB was configured as "i386-redhat-linux"...Using host

libthread_db library "/lib/libthread_db.so.1".

(gdb) break fork

Breakpoint 1 at 0x80482b0

(gdb) break vfork

Breakpoint 2 at 0x80482a0

(gdb) r

Starting program: /home/back/test

Breakpoint 1 at 0x400df6b0

Breakpoint 2 at 0x400df6f0

Breakpoint 2, 0x400df6f0 in __vfork () from

/lib/i686/libc.so.6

(gdb) disass

Dump of assembler code for function __vfork:

0x400df6f0 <__vfork>:

pop %ecx

0x400df6f1 <__vfork>:

mov $0xbe,%eax //0xbe 及120

0x400df6f6 <__vfork>:

int $0x80 //INT 0X80

0x400df6f8 <__vfork>:

cmp $0xfffff001,%eax

0x400df6fd

<__vfork>: jae 0x400df701 <__vfork>

0x400df6ff

<__vfork>: jmp *%ecx

0x400df701

<__vfork>: push %ecx

0x400df702

<__vfork>: cmp $0xffffffda,%eax

0x400df705

<__vfork>: jne 0x400df71a <__vfork>

0x400df707

<__vfork>: mov $0x2,%eax

0x400df70c

<__vfork>: int $0x80

0x400df70e

<__vfork>: cmp $0xfffff001,%eax

0x400df713

<__vfork>: jae 0x400df71a <__vfork>

0x400df715

<__vfork>: ret

0x400df716

<__vfork>: mov (%esp,1),%ebx

0x400df719

<__vfork>: ret

0x400df71a

<__vfork>: push %ebx

0x400df71b

<__vfork>: call 0x400df716

0x400df720

<__vfork>: add $0x7b934,%ebx

0x400df726

<__vfork>: xor %edx,%edx

0x400df728

<__vfork>: sub %eax,%edx

0x400df72a

<__vfork>: push %edx

Breakpoint 3, 0x400df6b0 in __libc_fork () from

/lib/i686/libc.so.6

(gdb) disass

Dump of assembler code for function __libc_fork:

0x400df6b0

<__libc_fork>: mov $0x2,%eax //为2

0x400df6b5

<__libc_fork>: int $0x80 //INT 0X80

0x400df6b7

<__libc_fork>: cmp $0xfffff001,%eax

0x400df6bc

<__libc_fork>: jae 0x400df6c3 <__libc_fork>

0x400df6be

<__libc_fork>: ret

0x400df6bf

<__libc_fork>: mov (%esp,1),%ebx

0x400df6c2

<__libc_fork>: ret

0x400df6c3

<__libc_fork>: push %ebx

0x400df6c4

<__libc_fork>: call 0x400df6bf

0x400df6c9

<__libc_fork>: add $0x7b98b,%ebx

0x400df6cf

<__libc_fork>: xor %edx,%edx

0x400df6d1

<__libc_fork>: sub %eax,%edx

0x400df6d3

<__libc_fork>: push %edx

0x400df6d4

<__libc_fork>: call 0x40040074

0x400df6d9

<__libc_fork>: pop %ecx

0x400df6da

<__libc_fork>: pop %ebx

0x400df6db

<__libc_fork>: mov %ecx,(%eax)

0x400df6dd

<__libc_fork>: or $0xffffffff,%eax

0x400df6e0

<__libc_fork>: jmp 0x400df6be <__libc_fork>

arch/i386/kernel/Process.c

00703: asmlinkage int sys_fork(struct pt_regs

regs) //pt_regs为各寄存器值

00704: {

00705: return do_fork(SIGCHLD,

regs.esp, ®s, 0, NULL, NULL);

00706: }

00707:

00708: asmlinkage int sys_clone(struct pt_regs

regs)

00709: {

00710: unsigned long

clone_flags;

00711: unsigned long

newsp;

00712: int __user

*parent_tidptr, *child_tidptr;

00713: 00714: clone_flags =

regs.ebx;

00715: newsp = regs.ecx;

00716: parent_tidptr = (int

__user *)regs.edx;

00717: child_tidptr = (int

__user *)regs.edi;

00718: if (!newsp)

00719: newsp = regs.esp;

00720: return

do_fork(clone_flags, newsp, ®s, 0, parent_tidptr,

child_tidptr);

00721: }

00733: asmlinkage int sys_vfork(struct pt_regs

regs)

00734: {

00735: return

do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL,

NULL);

00736: }

下面为do_fork()的定义:

kernel/Fork.c(01280)

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;

long pid =

alloc_pidmap(); //先分配一个pid

if (pid < 0)

return -EAGAIN;

//======================================================

// likely,unlikely为gcc预指令,用于优化程序,例如下

//面的unlikely为表明current->ptrace不大会为非零,因此gcc

//在编译程序时就可以优化,提高程序性能,详见gcc参考手册

//======================================================

if (unlikely(current->ptrace))

{

trace = fork_traceflag

(clone_flags); //根据current->ptrace和clone_flags取值

if (trace)

clone_flags

|= CLONE_PTRACE;

}

//======================================================

// copy_process()为主要函数

//======================================================

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); //done置0,并初始化list

}

if

((p->ptrace & PT_PTRACED) ||

(clone_flags & CLONE_STOPPED)) {

//如果处于调试,则必须马上设SIGSTOP信号

sigaddset(&p->pending.signal,

SIGSTOP); set_tsk_thread_flag(p,

TIF_SIGPENDING);//设置thread_info中flag字段

}

if (!(clone_flags

& CLONE_STOPPED))

wake_up_new_task(p,

clone_flags);//倘若没有设置CLONE_STOPPED标志马上唤醒新进程

else

p->state

=

TASK_STOPPED; //否则将其stat置为TASK_STOPPED

if (unlikely (trace))

{

current->ptrace_message

=

pid; //获取些调试跟踪信息

ptrace_notify

((trace << 8) | SIGTRAP);

}

if (clone_flags

& CLONE_VFORK) {

wait_for_completion(&vfork);//调度到了才返回

if (unlikely

(current->ptrace &

PT_TRACE_VFORK_DONE))

ptrace_notify

((PTRACE_EVENT_VFORK_DONE << 8) |

SIGTRAP);//获取些调试跟踪信息

}

} else {

free_pidmap(pid);

//出错处理

pid = PTR_ERR(p);

}

return pid;

}

Trackback:

http://tb.donews.net/TrackBack.aspx?PostId=1002743

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值