当前位置:   article > 正文

linux环境高级编程之fork、getpid、getppid函数_getpid的值什么时候为0

getpid的值什么时候为0

前段时间学习了fork函数创建进程,在fork创建后用execl函数来执行linux下的命令。



fork函数()

一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。

    一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。


用man fork 在linux下查看fork的用法

  1. #include <unistd.h>
  2. pid_t fork(void);

fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
    1)在父进程中,fork返回新创建子进程的进程ID;
    2)在子进程中,fork返回0;
    3)如果出现错误,fork返回一个负值;
我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

fpid的值为什么在父子进程中不同。“其实就相当于链表,进程形成了链表,父进程的fpid(p 意味point)指向子进程的进程id, 因为子进程没有子进程,所以其fpid为0.





getpid用来获取当前进程ID

getppid用来获取当前进程的父进程的ID

用法:  
#include <sys/types.h>
#include <unistd.h>

pid_t getpid(void);
pid_t getppid(void);



我写了一段代码用来加深理解

  1. [fanmaolin@Centeros duojincheng]$ vim testfork.c
  2. 1 /*********************************************************************************
  3. 2 * Copyright: (C) 2017 fanmaolin<fanmaolinn@gmail.com>
  4. 3 * All rights reserved.
  5. 4 *
  6. 5 * Filename: testfork.c
  7. 6 * Description: This file
  8. 7 *
  9. 8 * Version: 1.0.0(05/09/2017)
  10. 9 * Author: fanmaolin <fanmaolinn@gmail.com>
  11. 10 * ChangeLog: 1, Release initial version on "05/09/2017 07:28:18 PM"
  12. 11 *
  13. testfork.c
  14. 12 ********************************************************************************/
  15. 13
  16. 14 #include <sys/types.h>
  17. 15 #include <unistd.h>
  18. 16 #include <stdio.h>
  19. 17 int main ()
  20. 18 {
  21. 19 pid_t fpid=fork(); //fpid表示fork函数返回的值
  22. 20 int count=0;
  23. 21
  24. 22 if (fpid < 0)
  25. 23 printf("error in fork!");
  26. 24 else if (fpid == 0)
  27. 25 {
  28. 26 printf("我是子进程\n");
  29. 27 printf("i am the child process, my process id is %d\n",getpid());
  30. 28 printf("My Parents's process id is %d\n",getppid());
  31. 29 count++;
  32. 30 }
  33. 31 else
  34. 32 {
  35. 33 printf("我是父进程\n");
  36. 34 printf("i am the parent process, my process id is %d\n",getpid());
  37. 35 count++;
  38. 36 sleep(1);//因为不确定父子进程谁会先执行,加个延时保证父进程先执行
  39. 37 }
  40. 38 printf("统计结果是: %d\n",count);
  41. 39 return 0;
  42. 40 }


执行结果




可以看到父进程ID为65869
子进程ID为65870
从子进程用getppid()获取父进程ID为65869
返回两次统计结果:1

父子进程间不确定谁会先执行。


问题总结:


关于为什么这里会返回两次1呢?

当父进程在执行的过程中,执行到sleep(1)时CPU分配给父进程的时间片到了,这时会执行子进程,执行完子进程后再来执行父进程,所以两个1是并列打印的,下面我们来看一下去掉sleep(1)的执行结果。

  1. 36 #ifdef SLEEP
  2. 37 sleep(1);
  3. 38 #endif

在这里有个技巧,因为有时我会用到sleep(1)有时又不会用到,加一个宏定义,如果我想用sleep时,
[fanmaolin@Centeros duojincheng]$ gcc testfork.c -o DSLEEP
[fanmaolin@Centeros duojincheng]$ ./a.out 
我是父进程
i am the parent process, my process id is 66512
我是子进程
i am the child process, my process id is 66513
My Parents's process id is 66512
统计结果是: 1
统计结果是: 1

如果我不想用sleep时

[fanmaolin@Centeros duojincheng]$ gcc testfork.c
[fanmaolin@Centeros duojincheng]$ ./a.out 
我是父进程
i am the parent process, my process id is 66527
统计结果是: 1
[fanmaolin@Centeros duojincheng]$ 我是子进程
i am the child process, my process id is 66528
My Parents's process id is 1
统计结果是: 1




看深红色字体,没有用sleep时的执行结果,会发现My Parents's process id is 1
子进程的父进程ID变成了“1”,这是为什么呢?
我们来看一下,哪一个进程的ID是1
  1. [fanmaolin@Centeros duojincheng]$ ps aux
  2. USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
  3. root 1 0.0 0.1 19364 1264 ? Ss May08 0:03 /sbin/init

init进程的ID是1,原来我们不用sleep时,CPU如果先执行了父进程,父进程很快执行完了,子进程执行的时候没有了父进程,变成了孤儿进程,这个时候就被init进程收养了,所以子进程的父进程就变成了init进程。

在使用子进程的时候还要注意避免出现“僵尸进程”,所以要在父进程里给子进程“收尸”wait.

在分析类似问题时,一定要考虑到CPU时切片运行的,它留给每个程序的时间是有限的,差不多是ms级。
参考:
http://blog.csdn.net/jason314/article/details/5640969 fork
http://www.cnblogs.com/wannable/p/6021617.html  孤儿进程、僵尸进程、守护进程
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/210186
推荐阅读
相关标签
  

闽ICP备14008679号