从一段代码看fork()函数及其引发的竞争
首先来看一段从《UNIX环境高级编程》中摘录的一段很有意思的代码。借此我们再来谈谈fork()函数的一些问题。
#include "apue.h" static void charatatime(char*); int
main(void)
{
pid_t pid; if((pid=fork())<0){
err_sys("fork error");
}else if(pid==0){
charatatime("output from child\n");
}else{
charatatime("output from parent\n");
}
exit(0);
} static void
charatatime(char *str)
{
char *ptr;
int c; setbuf(stdout,NULL); /*set unbuffered*/
for(ptr=str;(c=*ptr++)!=0;)
putc(c,stdout);
}
这段代码究竟干了些啥呢?事实上很easy,首先用fork()函数生成了一个子进程。
事实上子进程能够看成是父进程的一个复制。
那么在如上的一段代码中,怎么推断是子进程还是父进程在运行呢?这时候我们就要来看看fork()函数的返回值了。
fork()的返回值:
当fork被调用之后,父子进程都从fork()之后開始执行。当然,父子进程要干的事情是不一样的,可是前面说了,子进程就是父进程的一个复制。它们事实上是共享一个代码段的。
这个时候,我们就要依靠fork()的返回值来推断当前执行的程序是父进程还是子进程了。fork()函数是个很有意思的家伙。它仅仅被调用了一次,可是却有两个返回值,分别返回到父子进程中。
在父进程中,fork()返回的是子进程的进程ID。值得注意的是,仅仅有在fork()函数的时候。父进程才干得到子进程的ID。否则的话就没有机会了。由于一个父进程能够有多个子进程。想要通过一个函数,得到某个确切的子进程的进程ID显然是比較困难的。
与父进程不同的是。子进程通常仅仅有一个父进程。因此能够通过一个叫getppid()的函数,找到自己父进程的ID。
而fork()在子进程中的返回值是0.这又是为什么呢?由于0一般是系统保留的进程号,因此不可能出现子进程的进程号为0的情况。正如上面的代码显示的那样,当pid==0的时候传递给子函数的字符数是“output from child”,否则那就是在父进程中。传递的字符串自然也成了“output from parent”。
接下来另一个问题,那就是,当fork()之后。父子进程事实上能够看成是两个独立的进程了。
那究竟是先运行父进程呢?还是先运行子进程呢?因此我们接着来谈谈进程间的竞争问题。
进程间的竞争(race condition):
那父子进程究竟是谁先执行呢?事实上一般来说,这是无法预測的,这要看内核的调度算法等一系列其它的因素。
我们能够会过来看看上面的代码。在父子进程共同调用的charatatime函数中,我们首先用setbuf取消了标准I/O的缓冲。这样在以下的for循环中,仅仅要putc一次,就会有对应的字符显示在shell上。依据上面的分析,我们能够预測的是,两个字符串可能并不会依照先后顺序完整地输出。由于进程间非常可能进行切换,一个字符串可能还没输完。内核就转而执行还有一个字符串的输出了。因此显示的shell中显示的结果非常可能是交叉输出的字符串。以下的图就为我们展示了结果:
非常显然。输出的结果是不可预測的,有时候是比較规则的输出,但有些时候就凌乱了。而这,就是进程间的竞争(race condition)。当然,解决竞争的方法有非常多。我们能够通过信号(signal)以及进程间通信(IPC)等待方式。来解决竞争的问题。这些就放到以后再说啦!
參考文献:《Advanced Programming in the UNIX Environment》
从一段代码看fork()函数及其引发的竞争的更多相关文章
- 一段代码看 Java 引用类型
Java 中的操作数(不知道叫什么,相对于 bytecode 而言,类似 CPU 的操作码和操作数)分为值类型和引用类型: 值类型就是直接存储最终数值的,如 char, int, float, dou ...
- 127个常用的JS代码片段,每段代码花30秒就能看懂(上)
127个常用的JS代码片段,每段代码花30秒就能看懂(上) JavaScript 是目前最流行的编程语言之一,正如大多数人所说:“如果你想学一门编程语言,请学JavaScript.” FreeCode ...
- Linux多任务编程之二:fork()函数及其基础实验(转)
来源:CSDN 作者:王文松 转自Linux公社 fork()函数 在 Linux 中创建一个新进程的唯一方法是使用fork()函数.fork()函数是 Linux 系统中一个非常重要的函数,和咱们 ...
- Linux环境fork()函数详解
Linux环境fork()函数详解 引言 先来看一段代码吧, 1 #include <sys/types.h> 2 #include <unistd.h> 3 #include ...
- 知识点查缺补漏贴02:Linux环境fork()函数详解
引言 先来看一段代码吧, #include <sys/types.h> #include <unistd.h> #include <stdio.h> #includ ...
- fork 函数的一点学习
昨天某位少年问了我一个问题,#include<stdio.h> int main() { fork(); fork(); fork(); printf("hello " ...
- fork函数详解(附代码)
虽然篇幅很长,但大多是易懂的代码,不用担心看不完 这里的所有操作,都将在下面的代码中有所体现 fork会拷贝当前进程的内存,并创建一个新的进程.如上图,fork函数会将整个进程的内存镜像拷贝到新的内存 ...
- 从linux0.11中起动部分代码看汇编调用c语言函数
上一篇分析了c语言的函数调用栈情况,知道了c语言的函数调用机制后,我们来看一下,linux0.11中起动部分的代码是如何从汇编跳入c语言函数的.在LINUX 0.11中的head.s文件中会看到如下一 ...
- js中闭包来实现bind函数的一段代码的分析
今天研究了一下bind函数,发现apply和call还可以有这样的妙用,顺便巩固复习了闭包. var first_object = { num: 42 }; var second_object = { ...
随机推荐
- Git源码管控规范
Git分支示意圖 Master:主分支.形成稳定的版本时,才将代码合并到Master分支 Relase:网站发布的分支.通过验证的Bug和功能需求,才合并到Release分支,并将稳定的版本进行备份 ...
- 由查找session IP 展开---函数、触发器、包
由查找session IP 展开---函数.触发器.包 一.userenv函数.sys_context函数 --查看当前client会话的session IP信息 SQL>select sys_ ...
- 20. Screen
一. Screen 1.什么是Screen Screen 是在多个进程间多路复用一个物理终端的全屏窗口管理器,Screen 也叫会话,一个Screen 会话中可以有多个 Screen 窗口, ...
- github使用-知乎的某小姐的一篇文章
作者:珊姗是个小太阳链接:http://www.zhihu.com/question/20070065/answer/79557687来源:知乎著作权归作者所有,转载请联系作者获得授权. 作为一个文科 ...
- 疯狂安卓Android自学笔记
开发者必备自学工具: 谷歌搜索:www.yundou.info Android原版开发文档 (英文) Doc http://www.phoned.cn/docs/reference/android/v ...
- IOS 中关于自定义Cell 上的按钮 开关等点击事件的实现方法(代理)
1.在自定义的Cell .h文件中写出代理,写出代理方法. @protocol selectButtonDelegate <NSObject> -(void)selectModelID:( ...
- 图的割点 桥 双连通(byvoid)
[点连通度与边连通度] 在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合.一个图的点连通度的定义为,最小割点集 ...
- 关于很简单的设计模式,ui-dao-database,以及JavaBean和util工具类
关于很简单的设计模式,ui-dao-database,以及JavaBean和util工具类 24. 三 / J2EE / 没有评论 简单的j2ee设计模式, UI通过DAO层访问数据库或者xml文 ...
- MYSQL存储过程中-流程控制语句
存储过程中常用的流程控制 复习下存储过程内部的语法 定义存储过程体的局部变量: 定义方法:DECLARE a INT DEFAULT 100或者DECLARE a INT ; SET a=100; ...
- 解决MySQL中文乱码的问题
遇到中文乱码问题,首先用status命令检查数据库的配置,如下: 上图会显示数据库配置的各项信息. 还可以用 show create database XXX,来显示创建数据库的时候的编码设置. 一般 ...