background image

们不予考虑。   

 

2.2.1 fork( )   

fork 在英文中是"分叉"的意思。为什么取这个名字呢?因为一个进程在运行中,如果使

用了 fork,就产生了另一个进程,于是进程就"分叉"了,所以这个名字取得很形象。下面就
看看如何具体使用 fork,这段程序演示了使用 fork 的基本框架:   

 

void main() 

{  

int i;   

if ( fork() == 0 )   

{  

/*  子进程程序 */  

for ( i = 1; i <1000; i ++ )   

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

}  

else  

{  

/*  父进程程序*/  

for ( i = 1; i <1000; i ++ ) 

printf("This is process process\n");   

}  

}  

 
程序运行后,你就能看到屏幕上交替出现子进程与父进程各打印出的一千条信息了。

如果程序还在运行中,你用 ps 命令就能看到系统中有两个它在运行了。   

 
那么调用这个 fork 函数时发生了什么呢?fork 函数启动一个新的进程,前面我们说过,

这个进程几乎是当前进程的一个拷贝:子进程和父进程使用相同的代码段;子进程复制父进
程的堆栈段和数据段。这样,父进程的所有数据都可以留给子进程,但是,子进程一旦开始
运行,虽然它继承了父进程的一切数据,但实际上数据却已经分开,相互之间不再有影响了,
也就是说,它们之间不再共享任何数据了。它们再要交互信息时,只有通过进程间通信来实
现,这将是我们下面的内容。既然它们如此相象,系统如何来区分它们呢?这是由函数的返
回值来决定的。对于父进程,fork 函数返回了子程序的进程号,而对于子程序,fork 函数则
返回零。在操作系统中,我们用 ps 函数就可以看到不同的进程号,对父进程而言,它的进
程号是由比它更低层的系统调用赋予的,而对于子进程而言,它的进程号即是 fork 函数对
父进程的返回值。在程序设计中,父进程和子进程都要调用函数 fork()下面的代码,而我
们就是利用 fork()函数对父子进程的不同返回值用 if...else...语句来实现让父子进程完成不
同的功能,正如我们上面举的例子一样。我们看到,上面例子执行时两条信息是交互无规则
的打印出来的,这是父子进程独立执行的结果,虽然我们的代码似乎和串行的代码没有什么
区别。   

 
读者也许会问,如果一个大程序在运行中,它的数据段和堆栈都很大,一次 fork 就要

复制一次,那么 fork 的系统开销不是很大吗?其实 UNIX 自有其解决的办法,大家知道,