zoukankan      html  css  js  c++  java
  • 被linux线程基础折磨的点滴——还是没得到完美的答案,但至少得到了所需

     1  #include<sys/types.h>
     2  #include<unistd.h>                                                          
     3  #include<stdio.h>
     4  #include<stdlib.h>
     5  int main(void)
     6  {
     7 
     8     printf("origin is %d
    ",getpid());
     9      printf("origin p is %d
    ",getppid());
    10 
    11      pid_t pid;
    12      pid=fork();
    13      if(pid>0)
    14       {
    15          printf("parent is %d
    ",getpid());
    16       }
    17      else if(pid==0)
    18     {
    19 
    20          printf("child is %d
    ",getpid());
    21          printf("child's parent is %d
    ",getppid());
    22     }
    23  }

    输出:

    很奇怪,为什么在子进程中调用父进程的PID会是1224,而parent明明是3973啊,有点晕。

    为了追踪代码进程,我在上述代码最后加了一个while(1)循环,不加还好,加了之后更晕了。

     1  #include<sys/types.h>
     2  #include<unistd.h>                                                          
     3  #include<stdio.h>
     4  #include<stdlib.h>
     5  int main(void)
     6  {
     7 
     8     printf("origin is %d
    ",getpid());
     9      printf("origin p is %d
    ",getppid());
    10 
    11      pid_t pid;
    12      pid=fork();
    13      if(pid>0)
    14       {
    15          printf("parent is %d
    ",getpid());
    16       }
    17      else if(pid==0)
    18     {
    19 
    20          printf("child is %d
    ",getpid());
    21          printf("child's parent is %d
    ",getppid());
    22     }
    23     while(1)
    24         ;
    25  }

    输出:

    啊,为什么又对了啊,加了一个循环阻塞之后,子进程中调用父进程的PID显示和parent一样了。

    这是为什么啊,各种资料论坛求助,得到一个回答:

    突然就觉得我理真理不远了,如果父进程结束,子进程再调用父进程PID确实是会有问题啊,知道这个之后,测试了,在parent的printf之后加wait或者pause函数,确实显示就正确。但是程序员血液刺激着我,就算父进程先销毁了(到底子进程还是父进程先销毁还得看操作系统的调度实现,就是不确定的意思?),那我在子进程中调用getppid函数得到的值为什么每次运行都一样啊,依照经验来看调用销毁了的东西应该会出现随机值的呀,看来这里还有学问。继续摸爬滚打,得到资料:

    在Linux中父进程先于子进程退出会造成子进程成为孤儿进程,而每当系统发现一个孤儿进程时,就会自
    动由1号进程(init)收养它,这样,原先的子进程就会变成init进程的子进程。

    这也就为什么每次在子进程中调用父进程都是显示1224,查看PID号,确实为1号进程(init)。这至少证明
    了,引起这个现象的原因,确实为父进程被销毁了(这是不是意味着在本就复杂的多进程程序中要考虑的事情更多了呢)。

    貌似,我终于可以放下这个问题继续学习了,但是,程序员有时几句简单程序,可能会带来意想不到的结果。
    我们总是不安寂寞,我也不知道为什么,就想加了个语句再试试,在main函数后面加个scanf阻塞一下,同时
    去除最后的while循环,
     1  #include<sys/types.h>
     2  #include<unistd.h>                                                          
     3  #include<stdio.h>
     4  #include<stdlib.h>
     5  int main(void)
     6  {
     7 
     8     printf("origin is %d
    ",getpid());
     9      printf("origin p is %d
    ",getppid());
    10     int a;
    11     printf("input a is....
    ");
    12     scanf("%d",&a);
    13      pid_t pid;
    14      pid=fork();
    15      if(pid>0)
    16       {
    17          printf("parent is %d
    ",getpid());
    18       }
    19      else if(pid==0)
    20     {
    21 
    22          printf("child is %d
    ",getpid());
    23          printf("child's parent is %d
    ",getppid());
    24     }
    25  }

    运行结果显示,子进程正确打印了了父进程的PID,这下是彻底晕了,难道忙活这么久,查阅这么多资料
    之后,发现还是不对?如上述代码,没有阻塞父进程的销毁,按理说它应该被销毁,子进程中应该打印parent
    为1224才对,为什么这个时候父进程就不被销毁了呢?实在没明白操作系统干了什么,毕竟自己不是写
    操作系统的人,有些东西了解即可。最后只能在一个用户层面得到一个总结:
    测试现象表明,确实存在父进程销毁使子进程被init收养;
    但是除了阻塞父进程的销毁(while循环或者pause函数等)之外,子进程还是可以得到父进程的ID,
    例如加了一个scanf,就这么一个scanf,让子进程得以访问父进程ID,也证明父进程没被销毁,那么问题来了,
    到底是什么原因呢,按理说就算前面有个阻塞,父进程也应该被销毁的,但事实上linux并没有,
    我并不清楚linux在这里的实现细节,只能在用户层面测试得到,只要你阻塞过父进程,他将存在,可以
    通过子进程访问。

    如果有人知道原因,请留言告诉我,不胜感激!这个问题,只能先到这了。。。

    拨开云雾:就在加了scanf之后,又测试了一把,我在想为什么系统会保留父进程,是不是因为我输入
    的数字a没有被使用的原因,于是,在上面代码仅仅增加一句,终于,我的猜想是正确的,使用一下a测试:
    1       if(pid>0)
    2       {
    3          a++4          printf("parent is %d
    ",getpid());
    5       }
    
    

    使用了a之后,输出结果:

    终于,如我所期了,父进程销毁,这样来理解linux系统的实现是可以接受的,操作系统认为你输入了
    数据,但还没去使用它,所以保留你的进程,如果你使用了那个变量之后,操作系统将其进程销毁。这个
    和输入缓冲区到内核实现有关系,至于底层到底是怎么的,我也就不关心了,但至少要了解到这个层面。自此,终于可以继续向下学习了^_^




  • 相关阅读:
    在energia中添加新的库
    KEIL3中出现的字符不对齐的情况解决办法
    VHDL硬件描述语言实现数字钟
    51单片机软件I2C驱动中的CY
    自问自答:在VB中如何实现像C++一样printf的功能
    [转][译] 分分钟学会一门语言之 Python 篇
    杂谈PID控制算法——最终篇:C语言实现51单片机中的PID算法
    Eclipse 安装与配置
    win10 环境安装 jdk 11.0.2
    解决网络问题神奇工具
  • 原文地址:https://www.cnblogs.com/yangguang-it/p/6525944.html
Copyright © 2011-2022 走看看