新手如何理解fork函数_华清远见

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

新手如何理解fork函数

我想,刚接触fork函数的时候,很多人都无法完全理解他,新手就更不用说了,为了让大家能正确理解fork函数,所以就写了一篇关于新手如何理解fork函数的文章。

首先我们来看看,什么是fork函数:计算机程序设计中的分叉函数。返回值:若成功调用一次则返回两个值,子进程返回0,父进程返回子进程标记;否则,出错返回-1。fork函数将运行着的程序分成2个(几乎)完全一样的进程,每个进程都启动一个从代码的同一位置开始执行的线程。这两个进程中的线程继续执行,就像是两个用户同时启动了该应用程序的两个副本。

正题开始了,对于刚刚接触Unix/Linux操作系统,在Linux下编写多进程的人来说,fork是最难理解的概念之一:它执行一次却返回两个值。

首先我们来看下fork函数的原型:

#i nclude

#i nclude

pid_t fork(void);

返回值:

负数:如果出错,则fork()返回-1,此时没有创建新的进程。最初的进程仍然运行。

零:在子进程中,fork()返回0

正数:在负进程中,fork()返回正的子进程的PID

其次我们来看下如何利用fork创建子进程。

创建子进程的样板代码如下所示:

pid_t child;

if((child = fork())<0)

/*错误处理*/

else if(child == 0)

/*这是新进程*/

else

/*这是最初的父进程*/

fock函数调用一次却返回两次;向父进程返回子进程的ID,向子进程中返回0,

这是因为父进程可能存在很多过子进程,所以必须通过这个返回的子进程ID来跟踪子进程,而子进程只有一个父进程,他的ID可以通过getppid取得。

下面我们来对比一下两个例子:

第一个:

#include

#include

int main()

{

pid_tpid;

int count=0;

pid = fork();

printf( "This is first time, pid = %d\n", pid );

printf( "This is second time, pid = %d\n", pid );

count++;

printf( "count = %d\n", count );

if ( pid>0 )

{

printf( "This is the parent process,the child has the pid:%d\n", pid );

}

else if ( !pid )

{

printf( "This is the child process.\n")

}

else

{

printf( "fork failed.\n" );

}

printf( "This is third time, pid = %d\n", pid );

printf( "This is fouth time, pid = %d\n", pid );

return 0;

}

运行结果如下:

问题:

这个结果很奇怪了,为什么printf的语句执行两次,而那句“count++;”的语句却只执行了一次接着看:

#include

#include

int main(void)

{

pid_tpid;

int count=0;

pid = fork();

printf( "Now, the pid returned by calling fork() is %d\n", pid );

if ( pid>0 )

{

printf( "This is the parent process,the child has the pid:%d\n", pid ); printf( "In the parent process,count = %d\n", count );

}

else if ( !pid )

{

printf( "This is the child process.\n");

printf( "Do your own things here.\n" );

count ++;

printf( "In the child process, count = %d\n", count );

}

else

{

printf( "fork failed.\n" );

}

return 0;

}

运行结果如下:

现在来解释上面提出的问题。

看这个程序的时候,头脑中必须首先了解一个概念:在语句pid=fork()之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了,这两个进程的代码部分完全相同,将要执行的下一条语句都是if ( pid>0 )……。

两个进程中,原先就存在的那个被称作“父进程”,新出现的那个被称作“子进程”。父子进程的区别除了进程标志符(process ID)不同外,变量pid的值也不相同,pid存放的是fork的返回值。fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:

1. 在父进程中,fork返回新创建子进程的进程ID;

2.在子进程中,fork返回0;

3.如果出现错误,fork返回一个负值;

fork出错可能有两种原因:(1)当前的进程数已经达到了系统规定的上限,这时errno的值被设置为EAGAIN。(2)系统内存不足,这时errno的值被设置为ENOMEM。

接下来我们来看看APUE2中对fork的说明:

The new process created by fork is called the child process. This function is called once but returns twice. The only difference in the returns is that the return value in the child is 0, whereas the return value in the parent is the process ID of the new child. The reason the child's process ID is returned to the parent is that a process can have more than one child, and there is no function that allows a process to obtain the process IDs of its children. The reason fork returns 0 to the child is that a process can have only a single parent, and the child can always call getppid to obtain the process ID of its parent. (Process ID 0 is reserved for use by the kernel, so it's not possible for 0 to be the process ID of a child.)

被fork创建的新进程叫做自进程。fork函数被调用一次,却两次返回。返回值唯一的区别是在子进程中返回0,而在父进程中返回子进程的pid。在父进程中要返回子进程的pid的原因是父进程可能有不止一个子进程,而一个进程又没有任何函数可以得到他的子进程的pid。

Both the child and the parent continue executing with the instruction that follows the call to fork. The child is a copy of the parent. For example, the child gets a copy of the parent's data space, heap, and stack. Note that this is a copy for the child; the parent and the child do not share these portions of memory. The parent and the child share the text segment (Section 7.6).

子进程和父进程都执行在fork函数调用之后的代码,子进程是父进程的一个拷贝。例如,父进程的数据空间、堆栈空间都会给子进程一个拷贝,而不是共享这些内存。

Current implementations don't perform a complete copy of the parent's data, stack, and heap, since a fork is often followed by an exec. Instead, a technique called copy-on-write (COW) is used. These regions are shared by the parent and the child and have their protection changed by the kernel to read-only. If either process tries to modify these regions, the kernel then makes

相关文档
最新文档