fork()与pid
写在前面:最近学到Linux的进程间通信,发现以前学的进程有点忘了,就找了一些博客来看,这篇博客讲的挺简单易懂的,就搬运来当笔记了,原文也是转载的找不到出处,有知道的可以告诉我,我再加上。
fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次,它可能有三种不同的返回值:
1)在父进程中,fork返回新创建子进程的进程ID;
2)在子进程中,fork返回0;
3)如果出现错误,fork返回一个负值;
创建新进程成功后,系统中出现两个基本完全相同的进程,这两个进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。此时,两个进程都从fork开始往下执行,只是pid不同。
有人可能疑惑为什么不是从#include处开始复制代码的?
看下图:
上图表示一个含有fork的程序,而fork语句可以看成将程序切为A、B两个部分。然后整个程序会如下运行:
step1、设由shell直接执行程序,生成了进程P。P执行完Part. A的所有代码。
step2、当执行到pid = fork();时,P启动一个进程Q,Q是P的子进程,和P是同一个程序的进程。Q继承P的所有变量、环境变量、程序计数器的当前值。
step3、在P进程中,fork()将Q的PID返回给变量pid,并继续执行Part. B的代码。
step4、在进程Q中,将0赋给pid,并继续执行Part. B的代码。
这里有三个点非常关键:
1、P执行了所有程序,而Q只执行了Part. B,即fork()后面的程序。(这是因为Q继承了P的PC-程序计数器)
2、Q继承了fork()语句执行时当前的环境,而不是程序的初始环境。
3、P中fork()语句启动子进程Q,并将Q的PID返回,而Q中的fork()语句不启动新进程,仅将0返回。
#include <unistd.h>
#include <sys/types.h>
main ()
{
pid_t pid;
printf("hello!\n");
pid=fork();
if (pid < 0)
printf("error in fork!");
else if (pid == 0)
printf("i am the child process, my process id is %d\n ",getpid());
else
printf("i am the parent process, my process id is %d\n",getpid());
printf("bye!\n");
}
这里可以看出parent process执行了printf("hello!\n"); 而child process 没有执行printf("hello!\n");
有一个让人很迷惑的例子:
#include <unistd.h>
#include <sys/types.h>
main ()
{
pid_t pid;
printf("fork!"); //printf("fork!\n")
pid=fork();
if (pid < 0)
printf("error in fork!\n");
else if (pid == 0)
printf("i am the child process, my process id is %d\n",getpid());
else
printf("i am the parent process, my process id is %d\n",getpid());
}
此时打印输出了两个fork!这不免让人以为是child process从#include处开始执行,所以也执行了printf("fork!"); 语句。
其实不然,出现这种问题的原因在于:
这就跟Printf的缓冲机制有关了,printf某些内容时,操作系统仅仅是把该内容放到了stdout的缓冲队列里了,并没有实际的写到屏幕上 。但是,只要看到有\n, 则会立即刷新stdout,因此就马上能够打印了.
mian函数(parent process)运行了printf("fork!") 后, "fork!"仅仅被放到了缓冲里,再运行到fork时,缓冲里面的 AAAAAA 被子进程(child process)继承了,因此在子进程度stdout缓冲里面就也有了"fork!"。所以,你最终看到的会是 "fork!" 被printf了2次!!!!
而mian函数(parent process)运行 printf("fork!\n")后,"fork!" 被立即打印到了屏幕上,之后fork到的子进程(child process)里的stdout缓冲里不会有"fork!"内容 因此你看到的结果会是"fork!" 被printf了1次!!!!
</div><link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e9f16cbbc2.css" rel="stylesheet"></div>
fork()与pid相关推荐
- linux父进程中显示子进程pid,请教linux下c语言函数fork父进程打印子进程的PID
请教linux下c语言函数fork父进程打印子进程的PID 关注:296 答案:2 信息版本:手机版 解决时间 2019-01-14 04:55 雨不眠的下 2019-01-13 12:23 用于 ...
- 进程控制 父进程子进程 fork pid
进程:正在运行的程序(分配资源:内存,CPU,IO等) 程序:有限指令的集合(静态:没有执行,存放在外存) 并发:多个任务"同时"执行. (处理器某一时刻最多只运行一个进程) 1. ...
- 一个fork短码的扩展版本
原本代码: 链接 int skip = !!fork() + 2*(!!fork()); for (uint32_t i=skip;i!=INT_MAX;i+=4) { } 这个是多进程加速循环的代码 ...
- 【Linux】多线程中使用fork()
(最核心的东西我在下面用红色字体标出来了,理解了那块,这些东西都是就理解了!) 在本篇文章开始之前,需要大家先了解线程和进程,这位大哥讲的言简意赅:进程和线程的主要区别(总结)_kuangsongha ...
- 进程创建函数fork()和vfork()
Linux下使用fork()创建一个新的进程,该函数不需要参数,返回值是一个进程id.对于不同的对象,分别是:新建的子进程id(返回给父进程),0(返回给创建的子进程)或者-1(子进程创建失败,返回给 ...
- c语言exit和return区别,在fork和vfork中使用
转自c语言exit和return区别,在fork和vfork中使用 exit函数在头文件stdlib.h中. 简述: exit(0):正常运行程序并退出程序: exit(1):非正常运行导致退出程序: ...
- linux 内核 fork,《Linux内核分析》之分析fork函数对应的系统调用处理过程
实验过程 [toggle hide="yes" title="实验过程" color="#f50000"] 1.在实验楼中shell终端依次 ...
- 【转】vfork 和 fork的区别
fork()与vfock()都是创建一个进程,那他们有什么区别呢?总结有以下三点区别: 1. fork ():子进程拷贝父进程的数据段,代码段 vfork ( ):子进程与父进程共享数据段 ...
- linux fork函数浅析
#include <sys/types.h> #include <unistd.h> /* 功能:复制进程 參数:无 返回值: 成功: 父进程:返回子进程id 子进程:返回0 ...
最新文章
- Oracle中concat与||区别(以及与mysql中concat函数区别)
- WAMP 2.2 配置与IIS共用单IP,多域名多网站配置方法
- canvas 实现图片局部模糊_Canvas模糊化处理图片、毛玻璃处理图片之stackblur.js
- uni-app微信小程序动态样式设置;微信小程序style行内式无效;微信小程序style行内式编译报错;微信小程序:style设置样式
- Spring集成Mybatis多数据源配置
- C#基础概念之延迟加载
- (转)python3 urllib.request.urlopen() 错误UnicodeEncodeError: 'ascii' codec can't encode characters...
- 计算机注册表管理,如何打开计算机注册表编辑器
- Element UI 进度条文字样式修改
- css 头像外圈白_如何使用css实现一个圆形头像框
- Android Studio 插件-Android Styler 的使用
- 视频算法经理岗位描述(工业方向)
- mysql 28000 远程_启用远程MySQL连接:错误1045(28000):拒绝用户访问
- 汇编——从一道题目浅谈分支结构
- python 抓取网页数据
- 设置控件的视觉效果(Win32)
- 什么是黄金ETF持仓?
- bootstrap table合并单元格mergeCell
- log4cplus:ERROR No appenders could be found for logger (AdSyncNamespace).
- 苹果id密码忘了怎么办?轻松重置,赶紧收藏!
热门文章
- 效率系列(四) VS常用快捷键
- swift UI专项训练39 用Swift实现摇一摇功能
- js面向对象的封装方法,【案例】
- Perl Nmap报告处理摸索(学习)
- 将Excel数据导入SQL Server数据库
- Hive常用的SQL命令操作
- 我的世界java版gamemode指令_我的世界切换生存和创造模式的命令是什么?
- 腾讯offer是什么样子_记一次腾讯社招前端面试(已拿到offer入职)
- 【错误记录】编译 Android 版本的 ijkplayer 报错 ( ./init-android.sh: 第 37 行: cd: android/contrib/: 没有那个文件或目录 )
- 【错误记录】Google Play 上架报错 ( 您的应用包含违反“元数据”政策的内容 | GP 政策中心 )