您的位置:首页 > 运维架构 > Linux

fork实例分析

2009-07-27 09:58 274 查看
进程的概念

程序:一个包含可以执行代码的文件,是一个静态的文件。

进程:一个开始执行但是还没有结束的程序的实例,就是可执行文件的具体实现。

为了区分各个不同的进程,系统给每一个进程分配了一个ID以便识别.;

为了充分的利用资源,系统还对进程区分了不同的状态.:将进程分为新建、运行、阻塞、就绪和完成五个状态.。新建表示进程正在被创建,运行是进程正在运行,阻塞是进程正在等待某一个事件发生,就绪是表示系统正在等待CPU来执行命令,而完成表示进程已经结束了系统正在回收资源。

 

进程的创建 (调用fork函数) :

#include

pid_t   fork();

创建:一个进程调用fork以后,系统会创建一个子进程。这个子进程和父进程不同的地方只有他的进程ID和父进程ID。

区分:通过fork的返回值来区分父进程与子进程,当fork掉用失败的时候 (内存不足或者是用户的最大进程数已到)fork返回-1,对于父进程fork返回子进程的ID,而对于fork子进程返回0。

一个子进程建立成功后,这个子进程将和他的父进程运行相同的程式,也就是两者所使用的变量值完全相同,于是子进程和父进程将同步运行一个程式。(各个系统的子进程和父进程的运行先后顺序可能不相同。)

 

#include <unistd.h>

#include <sys/types.h>

#include <stdio.h>

main()

{

   pid_t pid;

   pid=fork();

   if (pid < 0)

   {

       printf("error in fork!/n");

   }

   else if (pid == 0)

   {

      printf("i am the child process, my process id is %d/n",getpid());

   }

   else

   {

      printf("i am the parent process, my process id is %d/n",getpid());

   }

}

 

运行:

[root@linux]# gcc -o fork1 fork1.c

[root@linux]# ./fork1           

i am the child process, my process id is 32050

i am the parent process, my process id is 32049

程序执行:

pid=fork();OS创建一个新进程(子进程),这两个进程共享代码空间,但是数据空间是互相独立的,子程序数据空间的内容是父进程的完整拷贝,指令指针也完全相同,但只有一点不同,如果fork成功,子进程中fork的返回值是0,父进程中fork的返回值是子进程的进程号,如果fork不成功,父进程会返回错误。2个进程一直同时运行,而且步调一致,在fork之后,他们分别作不同的工作,也就是分岔了,出现了两行结果。至于哪一个最先运行,可能与操作系统有关。

Fork在英文中是叉子,分叉的意思,在函数fork中,取后面的意思。很形象的表示程序从这里分叉,fork函数创建了子进程,子进程和父进程同时(其实是cpu分时处理)开始运行分叉之后的程序。

 

看看下面一个例子:

#include <sys/types.h>

#include <unistd.h>

#include <stdio.h>

int main()

{

   int i;

   for( i= 0; i< 3; i++)

   {

      int pid= fork();

      if(pid== 0)

      {

         printf("son/n");

      }

      else

      {

         printf("father/n");

      }

   }

   return 0;

}

运行:

[root@linux]# gcc -o fork2 fork2.c

[root@linux]# ./fork2           

son

son

father

father

son

father

son

father

son

father

son

father

son

father

共打印出7个father7个son,每一个fork都打印father和son,而每一个father和son也都要进行一次fork,见下图详解:

for            i=0         1           2

               father     father     father

                                           son

                              son       father

                                            son

               son       father        father

                                             son

                              son         father

                                             son

其中每一行分别代表一个进程的运行打印结果。当产生子进程的时刻,子进程打印son,当子进程调用fork生成子子进程,它就提升为father。因此,该程序中father永远打印father,son在fork之前是son,fork之后就为father,同时生成新的son。

 

注:父进程为什么要创建子进程呢?因为 Linux是一个多用户操作系统,在同一时间会有许多的用户在争夺系统的资源,有时进程为了早一点完成任务就创建子进程来争夺资源.,一旦子进程被创建,父子进程一起从fork处继续执行,相互竞争系统的资源,有时候我们希望子进程继续执行,而父进程阻塞直到子进程完成任务,这个时候我们可以调用wait或者waitpid系统调用.。

#include

#include

pid_t wait(int *stat_loc);

pid_t waitpid(pid_t pid,int *stat_loc,int options);

wait 系统调用会使父进程阻塞直到一个子进程结束或者是父进程接受到了一个信号。如果没有父进程没有子进程或者他的子进程已经结束wait回立即返回。成功时 (因一个子进程结束)wait将返回子进程的ID,否则返回-1,并设置全局变量errno.stat_loc是子进程的退出状态。子进程调用 exit、_exit 或者是return来设置这个值. 为了得到这个值Linux定义了几个宏来测试这个返回值.

WIFEXITED:判断子进程退出值是非0 ;

WEXITSTATUS:判断子进程的退出值(当子进程退出时非0). ;

WIFSIGNALED:子进程由于有没有获得的信号而退出. ;

WTERMSIG:子进程没有获得的信号号(在WIFSIGNALED为真时才有意义)。

waitpid 等待指定的子进程直到子进程返回。

pid<-1 等待任何一个组ID等于pid绝对值的任何子进程。

pid=-1 等待任何子进程,相当于wait()。

pid=0 等待任何一个组ID和调用者的组ID相同的进程;

pid>0 等待任何子进程识别码为pid的子进程。

 stat_loc和wait的意义一样. options可以决定父进程的状 态.可以取两个值 WNOHANG:父进程立即返回当没有子进程存在时. WUNTACHED:当子进程结束时waitpid返回,但是子进程的退出状态不可得到.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux gcc 任务 测试 工作 os