Chinaunix首页 | 论坛 | 博客
  • 博客访问: 486971
  • 博文数量: 115
  • 博客积分: 5016
  • 博客等级: 大校
  • 技术积分: 1401
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-21 16:03
文章分类

全部博文(115)

文章存档

2013年(1)

2010年(17)

2009年(76)

2008年(21)

我的朋友

分类: LINUX

2009-07-01 21:04:44

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

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也就被打印了四次!
阅读(1162) | 评论(1) | 转发(0) |
0

上一篇:暑假倒计时

下一篇:linux内核中的fastcall

给主人留下些什么吧!~~

Mr_Yao2011-11-14 15:40:56

感觉不妥,在每个printf之前加一个fflush();或者setbuf(stdout,NULL)再试试吧。