Chinaunix首页 | 论坛 | 博客
  • 博客访问: 39064
  • 博文数量: 10
  • 博客积分: 236
  • 博客等级: 二等列兵
  • 技术积分: 110
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-20 21:15
文章分类
文章存档

2013年(3)

2012年(7)

我的朋友

分类: C/C++

2013-04-30 00:03:47

Linux系统下,fork()函数是用作创建进程的,注意了:不是创建线程。至于线程和进程的区别,简单提下:
1、线程包含在进程内部,一个进程可以同时进行多个线程;
2、一个进程是一项可执行的程序;
3、线程是执行命令的最小单位;
4、一个进程可以创建多个子进程。

这里就Linux系统下的进程创建,作出解释。
代码1:

点击(此处)折叠或打开

  1. #include<stdio.h>

  2. int main(void)
  3. {
  4.     printf("fork.\n");
  5.     int pid = 0;
  6.     pid = fork();
  7.     if (pid == 0) {
  8.         printf("child=%d.\n", getpid());
  9.         return -1;
  10.     }
  11.     printf("father=%d.\n", getpid());
  12.     return 0;
  13. }
代码执行之后:

点击(此处)折叠或打开

  1. one@one-Rev-1-0:~/programming/fork$ ./forks
  2. fork.
  3. father=7454.
  4. child=7455.
注意到,输出的结果中有父子进程的共同输出。
fork()进程创建之后,父进程中的pid=0首先被返回【1】
这个时候,父进程已经在12行执行,pid=0 进入的是子进程,然而子进程在return -1是返回【2】
这些都与操作系统的调度有关:操作系统将fork()函数的返回值保存到自身数据空间,然而子进程将在pid=0出分叉。

代码2:

点击(此处)折叠或打开

  1. #include<stdio.h>

  2. int main(void)
  3. {
  4.     printf("fork.\n");
  5.     int pid = 0;
  6.     pid = fork();
  7.     if (pid == 0) {
  8.         printf("child=%d.\n", getpid());        
  9.     }
  10.     printf("father=%d.\n", getpid());
  11.     return 0;
  12. }
这个代码只是将上面的代码1的第10行删除。
执行结果如下:

点击(此处)折叠或打开

  1. one@one-Rev-1-0:~/programming/fork$ ./forks
  2. fork.
  3. father=7682.
  4. child=7683.
  5. father=7683.
这个输出中,可以证明到:
子进程只是将父进程的代码在fork()之后复制了一份【3】
fork()之后,父进程继续执行,这个时候,通过getpid()函数得到的是子进程的pid【4】
注意到pid=0是父进程的id[5]

现在来总结一下前面5点:
在Linux系统中,通过fork()之后的程序,创建一个子进程。返回的进程id号保存在父进程中,子进程可以通过getpid()来获取自己的pid。子进程共享父进程代码,但是不共享数据空间。当fork()完成之后,父进程继续执行。子进程可以执行父进程的代码。

如果说基本理解了,那么现在看一下下面这个代码:

点击(此处)折叠或打开

  1. #include<stdio.h>

  2. int main(void)
  3. {
  4.     int pid = 0;
  5.     int i;
  6.     for (i = 0; i < 3; i++) {

  7.         pid = fork();
  8.         printf("*");
  9.     }

  10.     return 0;

  11. }
这个代码很简单就是一个循环,里面创建子进程,并且输出结果。
那么这个输出结果是?
a、8    b、16    c、24   d、30

答案是24个星花(*)。
先看一下输出结果:

点击(此处)折叠或打开

  1. one@one-Rev-1-0:~/programming/fork$ cat 2fork.txt
  2. pid=8895*
  3. pid=8895*
  4. pid=8895*
  5. pid=8895*
  6. pid=8895*
  7. pid=8898*
  8. pid=8895*
  9. pid=8897*
  10. pid=8897*
  11. pid=8895*
  12. pid=8897*
  13. pid=8899*
  14. pid=8896*
  15. pid=8896*
  16. pid=8896*
  17. pid=8896*
  18. pid=8896*
  19. pid=8901*
  20. pid=8896*
  21. pid=8900*
  22. pid=8900*
  23. pid=8896*
  24. pid=8900*
  25. pid=8902*
现在统计一下:
8895:7
8896:7
8897:3
8898:1
8899:1
8900:3
8901:1
8902:1
总计:24.
这个怎么来的?
其实这样撇开来看:
【1】父进程先执行3次,注意了,操作系统中是以堆栈的形式存储的。
【2】最先返回的是i=2是父进程创建的子进程。
【3】注意了,在父进程执行3次的过程中,父进程是直接输出的,但是父进程创建的子进程是保存在堆栈中,也就是说,父进程在i=2的时候,将最后有父进程创建的子进程压到堆栈中,此时堆栈保存的是两个父进程的id。
【4】当最后一个有父进程创建的子进程输出完毕之后,就是i=1时由父进程创建的子进程。
【5】i=1是父进程创建了一个【11】子进程,别且该子进程自己也创建了【12】子进程。所以为了保存【12】子进程的id必须要保存父进程id号和【11】子进程的id号,这就导致了上面怪异的输出结果。对于其他的子进程,推断类似。

说白了,主要还是要理解:
【1】fork一下,返回两下
【2】存储数据,需要堆栈[,输出的时候,不一定按照堆栈输出的,可能中间有查找工作,这个时候,就有可能打乱输出结果]

好了,就这些吧。

 










阅读(5493) | 评论(0) | 转发(0) |
0

上一篇:install and configure the jdk on Ubuntu @JAVA

下一篇:没有了

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