设为首页 收藏本站
查看: 367|回复: 0

[经验分享] linux下 fork题 转

[复制链接]

尚未签到

发表于 2016-2-1 09:31:42 | 显示全部楼层 |阅读模式
Linux下fork()函数浅析
实验环境:Ubuntu 3.5.0-32-generic
头文件:

#include <unistd.h>
#include <sys/types.h>
函数原型:
pid_t fork(void);
(pid_t 是一个宏定义,其实质是int 被定义在#include<sys/types.h>中)
返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1

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

  一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。当子进程被调度得以执行时,其从程序中fork()语句下一条指令开始执行。

  由fork创建的新进程被称为子进程(child process)。该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0,而父进程的返回值则是新进程(子进程)的进程id。将子进程id返回给父进程的理由是:因为一个进程的子进程可以多于一个,没有一个函数使一个进程可以获得其所有子进程的进程id。 对子进程来说,之所以fork返回0给它,是因为它随时可以调用getpid()来获取自己的pid;也可以调用getppid()来获取父进程的id。(进程id 0总是由交换进程使用,所以一个子进程的进程id不可能为0 )。

Program1:


[cpp]viewplaincopy



  • #include<stdlib.h>
  • #include<stdio.h>
  • #include<sys/types.h>
  • #include<unistd.h>

  • intmain(intargc,char*argv[])
  • {
  • pid_tpid=0;

  • printf("Beforefork!--with\"\\n\"\n");
  • printf("Beforefork!--without\"\\n\"");

  • pid=fork();

  • if(pid==0){
  • printf("Childprocess!\n");
  • pid_tpid_child=getpid();
  • printf("Pid=%d\n",pid_child);
  • }

  • elseif(pid>0){
  • printf("Parentprocess!\n");
  • pid_tpid_parent=getpid();
  • printf("Pid=%d\n",pid_parent);
  • }

  • else{
  • printf("forkfailure!\n");
  • }

  • exit(0);
  • }

Output:
DSC0000.jpg
程序浅析:
在父进程中利用fork()系统调用生成子进程,此时父进程pid_parent = 3804,子进程pid_child = 3805;生成子进程后,父进程继续执行输出父进程pid,到遇见exit(0)后父进程退出,并退出Linux控制台。调度函数调度执行子进程,子进程在从程序fork语句下一语句开始执行,输出子进程pid,直到遇见exit(0)结束。
在程序中字符串"Before fork!--with "\n""与字符串"Before fork--without "\n""的输出语句均在原程序中fork语句前执行,但前者只在父进程中输出一次,而后者在父、子进程都有输出一次,主要在于输出语句“printf”的实现中对输出缓存的处理,输出语句中的换行符"\n"会强制刷新输出缓存,故带换行符的输出语句只在父进程中输出一次,而后者在父进程结束后仍在输出缓存中保存,在子进程执行至输出语句printf("Child process!\n")时一并输出。
Program2:

[cpp]viewplaincopy



  • #include<stdlib.h>
  • #include<stdio.h>
  • #include<sys/types.h>
  • #include<unistd.h>

  • intmain(intargc,char*argv[])
  • {
  • pid_tpid=0;
  • intcount=13;

  • pid=fork();

  • if(pid==0){
  • sleep(1);
  • count=31;
  • printf("Childprocess!\nPid=%d\n",getpid());
  • }

  • elseif(pid>0){
  • wait(NULL);
  • printf("Parentprocess!\nPid=%d\n",getpid());
  • }

  • else{
  • printf("Forkerror!\n");
  • }

  • printf("Thereare%dapples!\n",count);

  • exit(0);
  • }

Output:

DSC0001.jpg

   wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。

在本程序中,父进程调用fork()函数创建子进程3837后,父进程继续执行,当执行到wait(NULL);时,阻塞自己,调度函数调度子进程开始执行,子进程结束后,父进程从阻塞前的地方开始继续执行,此时子进程对count值的改变并未传递至父进程,输出count值,直到exit(0)结束。



Program 3:

[cpp]viewplaincopy



  • #include<stdlib.h>
  • #include<stdio.h>
  • #include<sys/types.h>
  • #include<unistd.h>

  • intmain(intargc,char*argv[])
  • {
  • fork();
  • fork()&&fork()||fork();
  • fork();
  • exit(0);
  • }

以上程序共有多少个进程?
DSC0002.jpg

共创建19个新进程,与父进程一共20个进程。

我们对以上程序作一些修改,让每个进程执行均有一个标志性的输出,即可验证我们的猜想!
Program 3‘:

[cpp]viewplaincopy



  • #include<stdlib.h>
  • #include<stdio.h>
  • #include<sys/types.h>
  • #include<unistd.h>

  • intmain(intargc,char*argv[])
  • {
  • fork();
  • fork()&&fork()||fork();
  • fork();

  • printf("Endofprocess!\n");
  • exit(0);
  • }

Output:
DSC0003.jpg

由以上程序可见,共执行输出语句20次,即我们的分析得以验证:共20个进程。
*由于某些原因,先前所用Ubuntu系统故障,此程序在centos平台完成测试。
附录:
wait()与waitpid()浅析
sleep()系统调用浅析

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-172144-1-1.html 上篇帖子: Linux启动类故障分析 下篇帖子: fedora 21 + win8 开机启动项的顺序设为默认启动win8
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表