文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>关于fork函数的深入顿悟

关于fork函数的深入顿悟

时间:2009-07-01  来源:litary1986

今天同学给了我一个程序,让我解释一些执行诡异的结果,拿过程序我感觉非常简单,但是一运行,结果居然和我所想的不一样,在linux下做编程也不是一天两天了,有几分失落的情况下更感觉自己的无知,深入分析了一下,终于找出了最终的原因!写在这里用以警戒自己,如果有人有兴趣也可以自己跑跑,感觉很不错的一个程序!
程序代码如下:
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void sigusr1(int sig)
{
  printf("get signal\n");
}

int main()
{
    int pid;
    int ppid;
    if( signal( SIGRTMIN, sigusr1 ) == SIG_ERR ){
          perror( "Can not catch SIGRTMIN!" );
      }
    if( (pid=fork()) == -1 ) 
        perror("fork error!");
    else if( pid == 0 )    /*child deal*/
    {
        sleep(1);
        ppid = getppid();
        kill( ppid, SIGRTMIN );
    }
    if( (pid=fork()) == -1 ) 
        perror("fork");   
    else if( pid == 0 )    /*child deal*/
    {   
        ppid = getppid();
        kill( ppid, SIGRTMIN );
        sleep(2);
    }
    sleep(3);
      return 0;
}
可以看一下,你认为get signal应该打印出几次?一种很直接的感觉就是两个子进程,应该是执行两次。
错,可以运行一下,是三次!
为什么呢……
呵呵,继续分析一下,在两个子进程创建之后分别添加两条打印不同字符串的语句,比如下面的改法:
int main()
{
    int pid;
    int ppid;
    if( signal( SIGRTMIN, sigusr1 ) == SIG_ERR ){
          perror( "Can not catch SIGRTMIN!" );
      }
    if( (pid=fork()) == -1 ) 
        perror("fork error!");
    else if( pid == 0 )    /*child deal*/
    {
        sleep(1);
        ppid = getppid();
        kill( ppid, SIGRTMIN );
    }
    printf("aa\n");
    if( (pid=fork()) == -1 ) 
        perror("fork");   
    else if( pid == 0 )    /*child deal*/
    {   
        ppid = getppid();
        kill( ppid, SIGRTMIN );
        sleep(2);
    }
    sleep(3);
    printf("bb\n");
      return 0;
}
执行一下,你会发现aa打印了2次,而bb出现了4次,有没有什么新的想法或者顿悟?
如果还没有,那我告诉你……还是再深入分析一下吧!用下面的代码去分析:
int main()
{
    int pid;
    int ppid;
    if( signal( SIGRTMIN, sigusr1 ) == SIG_ERR ){
          perror( "Can not catch SIGRTMIN!" );
      }
    if( (pid=fork()) == -1 ) 
        perror("fork error!");
    else if( pid == 0 )    /*child deal*/
    {
        sleep(1);
        printf ( "the pid is %d\n", getpid() );
        ppid = getppid();
        printf ( "the ppid is %d\n", ppid );
        kill( ppid, SIGRTMIN );
    }
    if( (pid=fork()) == -1 ) 
        perror("fork");   
    else if( pid == 0 )    /*child deal*/
    {   
        printf ( "the pid is %d\n", getpid() );
        ppid = getppid();
        printf ( "the ppid is %d\n", ppid );
        kill( ppid, SIGRTMIN );
        sleep(2);
    }
    sleep(3);
      return 0;
}
看一下吧,添加了这些语句,你应该有了新的想法,对了,就是这样,fork函数创建的子进程要继承(写时复制)父进程的用户空间,也就是相应的代码段和数据段,不过它的下一步执行是从被创建的那一点开始的,也就是说第一个子进程在被创建后也执行了下面的代码,打印了aa,创建了子进程,打印了bb,这样第二个fork函数就被执行了两次,创建了两个新的子进程,这两个子进程的区别就是父进程不同,他们都执行了后面的sleep并且打印了bb,所以总共有三个子进程,也就发送了三个信号,bb也就被打印了四次!
相关阅读 更多 +
排行榜 更多 +
僵尸运行3d城市逃生

僵尸运行3d城市逃生

冒险解谜 下载
顶尖猎人罗迪和凯茜

顶尖猎人罗迪和凯茜

冒险解谜 下载
火柴人飞爪忍者

火柴人飞爪忍者

冒险解谜 下载