每天进步一点点——论fork()函数与Linux中的多线程编程
转载请说明出处:http://blog.csdn.net/cywosp/article/details/27316803
#include <unistd.h>
// On success, The PID of the process is returned in the parent, and 0 is returned in
the child. On failure,// -1 is returned in the parent, no child process is created, and errno is set appropriately.pid_t fork (void);
-write)技术来处理。调用fork()之后,父进程与子进程的运行顺序是我们无法确定的(即调度进程使用CPU),意识到这一点极为重要,由于在一些设计不好的程序中会导致资源竞争,从而出现不可预知的问题。下图为写时拷贝技术处理前后的示意图:
在Linux系统中,经常存在很多对文件的操作,fork()的运行将会对文件操作带来一些小麻烦。因为子进程会将父进程的大多数数据拷贝一份,这样在文件操作中就意味着子进程会获得父进程全部文件描写叙述符的副本,这些副本的创建方式类似于dup()函数调用,因此父、子进程中相应的文件描写叙述符均指向同样的打开的文件句柄,并且打开的文件句柄包括着当前文件的偏移量以及文件状态标志,所以在父子进程中处理文件时要考虑这样的情况,以避免文件内容出现混乱或者别的问题。下图为运行fork()调用后文件描写叙述符的相关处理及其变化:
data),以及堆内存段(heap segment)。在多处理器环境下,多个线程能够同一时候运行,假设线程数超过了CPU的个数,那么每一个线程的运行顺序将是无法确定的,因此对于一些全局共享数据据须要使用同步机制来确保其的正确性。
1. 尽管仅仅将发起fork()调用的线程复制到子进程中,但全局变量的状态以及全部的pthreads对象(如相互排斥量、条件变量等)都会在子进程中得以保留,这就造成一个危急的局面。比如:一个线程在fork()被调用前锁定了某个相互排斥量,且对某个全局变量的更新也做到了一半,此时fork()被调用,全部数据及状态被复制到子进程中,那么子进程中对该相互排斥量就无法解锁(由于其并不是该相互排斥量的属主),假设再试图锁定该相互排斥量就会导致死锁,这是多线程编程中最不愿意看到的情况。同一时候,全局变量的状态也可能处于不一致的状态,由于对其更新的操作仅仅做到了一半相应的线程就消失了。fork()函数被调用之后,子进程就相当于处于signal
handler之中,此时就不能调用线程安全的函数(用锁机制实现安全的函数),除非函数是可重入的,而仅仅能调用异步信号安全(async-signal-safe)的函数。fork()之后,子进程不能调用:
- malloc(3)。由于malloc()在訪问全局状态时会加锁。
- 不论什么可能分配或释放内存的函数,包含new、map::insert()、snprintf() ……
- 不论什么pthreads函数。你不能用pthread_cond_signal()去通知父进程,仅仅能通过读写pipe(2)来同步。
- printf()系列函数,由于其它线程可能恰好持有stdout/stderr的锁。
- 除了man 7 signal中明白列出的“signal安全”函数之外的不论什么函数。
2. 由于并未运行清理函数和针对线程局部存储数据的析构函数,所以多线程情况下可能会导致子进程的内存泄露。另外,子进程中的线程可能无法訪问(父进程中)由其它线程所创建的线程局部存储变量,由于(子进程)没有不论什么对应的引用指针。
#include <pthread.h>
// Upon successful completion, pthread_atfork() shall
return a value of zero; otherwise, an error number shall be returned to indicate the error.// @prepare 新进程产生之前被调用// @parent 新进程产生之后在父进程被调用// @child 新进程产生之后,在子进程被调用int pthread_atfork (void (*prepare)
(void), void (*parent) (void), void (*child)
(void));
每天进步一点点——论fork()函数与Linux中的多线程编程的更多相关文章
- linux中c语言编程main函数和参数
linux下main函数的的标准调用函数的标准形式 int main(int char,char *argv[]) 在main函数的两个参数中,argc必须是整型变量,其是命令行的参数的数目,argv ...
- Linux多任务编程之二:fork()函数及其基础实验(转)
来源:CSDN 作者:王文松 转自Linux公社 fork()函数 在 Linux 中创建一个新进程的唯一方法是使用fork()函数.fork()函数是 Linux 系统中一个非常重要的函数,和咱们 ...
- Linux C 中 fork() 函数详解
一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork() 函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同 ...
- Fork函数初识
fork函数用于创建子进程,典型的调用一次,返回两次的函数.其中调用进程返回子进程的PID,而子进程则返回0.但是两个进程的执行顺序是不定的. fork函数调用完成以后父进程的虚拟存储空间被拷贝给了子 ...
- fork()函数详解
原文链接:http://blog.csdn.net/jason314/article/details/5640969 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函 ...
- linux中fork()函数详解(原创!!实例讲解) (转载)
一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程, 也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不 ...
- (转)linux中fork()函数详解
一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同, ...
- linux中fork()函数详解
一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同, ...
- linux中fork()函数详解(转)
转自:http://blog.csdn.net/jason314/article/details/5640969 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过 ...
随机推荐
- 《精通Python设计模式》学习结构型之适配器模式
大名鼎鼎~~ 在兼容老系统和其它系统外调用时,用得着~ class Synthesizer: def __init__(self, name): self.name = name def __str_ ...
- Pig的安装和简单使用
1.Pig是基于hadoop的一个数据处理的框架. MapReduce是使用java进行开发的,Pig有一套自己的数据处理语言,Pig的数据处理过程要转化为MR来运行.2.Pig的数据处理语言是数据流 ...
- R语言编程艺术(1)快速入门
这本书与手上其他的R语言参考书不同,主要从编程角度阐释R语言,而不是从统计角度.因为之前并没有深刻考虑这些,因此写出的代码往往是一条条命令的集合,并不像是“程序”,因此,希望通过学习这本书,能提高编程 ...
- QT防止程序启动两次的方法
为了使QT 能保证只创建一个实例来进行, 对windows和linux分别采取了全局互斥变量和文件锁的方法. Q_OS_WIN32宏用来表示编译运行的目标平台是windows,Q_OS_LINUX则标 ...
- 【工具】获取pojo类属性,并写入表格
1.添加依赖 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependency> <g ...
- 预备作业02:体会做中学(Learning By Doing)
1.很惭愧,我并没有什么技能能强过大家. 2...... 3.我觉得培养一个技能,必须要通过勤勉的练习,认真的学习,还有不断地结合实践. 4.我觉得我学习<程序设计与数据结构>之后应该对程 ...
- 组装者模式在React Native项目中的一个实战案例
前言 在实际的开发中,如果遇到多个组件有一些共性,我们可以提取一个BaseItem出来,然后在多个组件中进行复用,一种方式是通过继承的方式,而今天我们要说的是另一种方式--组装者模式. 什么是组装者模 ...
- zoj 3983 Crusaders Quest 思维+枚举
题目链接 这道题意思是: 给你一个长度为9的字符串,且只有3个a.3个g.3个o 问,你可以选择删除一段连续的串或者单个的字符也可以不删,最多会出现几个三子相连的子串 比如:agoagoago只有将两 ...
- 树莓派与微信公众号对接(python)
一 内网穿透,让外网可以访问树莓派 二 树莓派对接微信 需要安装webpy和python-lxml git clonegit://github.com/webpy/webpy.git ln -s `p ...
- [ 转载 ] Mysql 数据库常用命令
完整的创建数据库例子: >create database db_test default character set utf8 collate utf8_general_ci; >use ...