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:
-
#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:
程序浅析:
在父进程中利用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:
-
#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:
wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status
返回,而子进程的进程识别码也会一快返回。如果不在意结束状态值,则参数status 可以设成NULL。
在本程序中,父进程调用fork()函数创建子进程3837后,父进程继续执行,当执行到wait(NULL);时,阻塞自己,调度函数调度子进程开始执行,子进程结束后,父进程从阻塞前的地方开始继续执行,此时子进程对count值的改变并未传递至父进程,输出count值,直到exit(0)结束。
Program 3:
-
#include<stdlib.h>
-
#include<stdio.h>
-
#include<sys/types.h>
-
#include<unistd.h>
-
-
intmain(intargc,char*argv[])
-
{
-
fork();
-
fork()&&fork()||fork();
-
fork();
-
exit(0);
-
}
以上程序共有多少个进程?
共创建19个新进程,与父进程一共20个进程。
我们对以上程序作一些修改,让每个进程执行均有一个标志性的输出,即可验证我们的猜想!
Program 3‘:
-
#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:
由以上程序可见,共执行输出语句20次,即我们的分析得以验证:共20个进程。
*由于某些原因,先前所用Ubuntu系统故障,此程序在centos平台完成测试。
附录:
wait()与waitpid()浅析
sleep()系统调用浅析
分享到:
相关推荐
从一道面试题谈linux下fork的运行机制
linux面试题看FORK()
linux 进程 线程 fork 的深入思考 一道面试题的思考
fork函数只能在类Unix的系统中使用,用于创建子线程,这里总结了C语言的fork函数在Linux中的进程操作及相关面试题讲解,先来看一下C语言程序的存储空间与进程示意:
fork()函数在Linux下可以用于产生一个子进程,这里我们挑选了两个fork相关的面试题,来看一下Linux下C语言的fork()子进程函数用法及相关问题解析
3.6.1 fork系统调用 58 3.6.2 exec系统调用 59 3.6.3 wait系统调用 60 3.6.4 exit系统调用 62 3.6.5 进程的一生 63 3.7 与调度相关的系统调用及应用 63 习题3 65 第4章 内存管理 67 4.1 Linux的内存管理概述 67 ...
(2)将该任务挂起,再转后台,再转前台,查看进程的状态变迁过程。 6、编写程序实现通过Windows客户端对Linux服务器端进行相关网络信息配置。(25分) 要求:(1)新修改服务器的IP 地址的构成方式:网络号为192.168.2.0...
打通Linux脉络系列:进程、线程和调度 ...2.1 fork 和 vfork 区别 2.2 写时拷贝技术 2.3 Linux线程的实现本质 2.4 孤儿进程的托孤,SUBREAPER 练习题 第三部分大纲 练习题 第四部分大纲 练习题
Linux Cpp 后台开发进阶学习 本项目用于Linux Cpp后台开发秋招学习,内容主要涵盖以下几个部分:Cpp...Linux进程创建之浅析fork() Linux环境编程 Linux 系统编程(一)Linux开发环境+Visual Studio Code配置
Java并发Fork-Join框架原理解析.docx JAVA核心知识整理.pdf JAVA核心知识点整理.pdf Java面试笔记.docx JAVA面试题解惑系列.pdf Java面试题(基础).pdf JVM 实用参数系列 - v1.0.pdf JVM与性能优化知识点整理.pdf ...
《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...
内含fork学习的各种例子代码,可在linux环境下运行。 部分代码摘自csapp第八章课后习题。
解: linux 系统创建进程都是用 fork() 系统调用创建子进程. 当首次调用新创建进时,其入口在哪里? 解: 由 fork() 系统调用创建的新进程被称为子进程。该函数被调用一次,但返回两次。如果 fork()进程调用成功,两次...
本书内容权威,概念清晰,阐述精辟,对于所有层次UNIX/Linux程序员都是一本不可或缺的参考书。 目录 ----------------------------------------------------------- 第1章unix基础知识1 1.1 引言1 1.2 unix...
本书内容权威,概念清晰,阐述精辟,对于所有层次UNIX/Linux程序员都是一本不可或缺的参考书。 目录 ----------------------------------------------------------- 第1章unix基础知识1 1.1 引言1 1.2 unix...
ee笔试题 免费的编程中文书籍索引 免费的编程中文书籍索引,欢迎投稿。 [removed][removed] 参与交流 欢迎大家讲珍藏已久的经典免费书籍共享出来,您可以: 使用 以及 Pull Request 发邮箱给我 来 交流 注:看到有人...
集合、JVM、多线程、并发编程、设计模式、SpringBoot、SpringCloud、Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、MongoDB、Redis、MySQL、RabbitMQ、Kafka、Linux、Netty、Tomcat、Python、HTML、...