UNIX环境高级编程——线程和fork
当线程调用fork时,就为子进程创建了整个进程地址空间的副本。子进程通过继承整个地址空间的副本,也从父进程那里继承了所有互斥量、读写锁和条件变量的状态。如果父进程包含多个线程,子进程在fork返回以后,如果紧接着不是马上调用exec的话,就需要清理锁的状态。
在子进程内部只存在一个线程,它是由父进程中调用fork的线程的副本构成的。如果父进程中的线程占有锁,子进程同样占有这些锁。问题是子进程并不包含占有锁的线程的副本,所以子进程没有办法知道它占有了哪些锁,并且需要释放哪些锁。
当多线程进程调用fork创建子进程时,Pthreads指定只有那个调用fork的线程在子进程内存在(表示子进程中只有调用线程这个线程)。尽管当从fork调用返回时,只有调用线程在子进程中存在,所有其他的Pthreads线程状态(互斥量、读写锁和条件变量的状态以及线程私有数据键)仍保留为与调用fork时相同的状态。在子进程中,线程拥有与在父进程内相同的状态。
注:fork调用不会影响互斥量的状态。如果它在父进程中被锁住,则它在子进程中被锁!
因为没有调用线程私有数据销毁和清除处理函数,你可能需要担心存储泄漏问题。
1.fork处理器
int pthread_atfork(void (*prepare)(void),void (*parent)(void),void(*child)(void));//返回值:若成功则返回0,否则返回错误编号
Pthreads增加了pthread_atfork ”fork处理器”机制以允许你的代码越过fork调用保护数据和不变量。这与atexit有点类似,后者在一个进程终止时允许程序执行清除操作。
使用pthread_atfork,你需要提供三个独立的处理函数地址。prepare fork处理程序由父进程调用fork创建子进程之前调用,这个fork处理程序的任务是获得父进程定义所有的锁。parent fork处理程序在fork创建了子进程以后,但在fork返回之前在父进程环境中调用,这个fork处理程序的任务是对prepare fork处理程序获得的所有锁进行解锁。child fork处理程序在fork返回之前在子进程环境中调用,与parent fork处理程序一样,child fork处理程序也必须释放parent fork处理程序获得的所有锁。
可以调用pthread_atfork多次注册多组回调函数,这时,回调函数调用的顺序规定如下:
- prepare函数调用顺序与它们的注册顺序相反;
- parent和child函数的调用顺序与注册顺序相同。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h> pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER; void prepare(void)
{
printf("preparing locks...\n");
pthread_mutex_lock(&lock1);
pthread_mutex_lock(&lock2);
} void parent(void)
{
printf("parent unlocking locks...\n");
pthread_mutex_unlock(&lock1);
pthread_mutex_unlock(&lock2);
} void child(void)
{
printf("child unlocking locks...\n");
pthread_mutex_unlock(&lock1);
pthread_mutex_unlock(&lock2);
} void *thr_fn(void *fn)
{
printf("thread started...\n");
pause();
return 0;
} int main(void)
{
pid_t pid;
pthread_t tid;
//BSD系统和MAC OS系统不支持pthread_atfork
#if defined(BSD) || defined(MACOS)
printf("pthread_atfork is unsupported\n");
#else
pthread_atfork(prepare, parent, child);
pthread_create(&tid, NULL, thr_fn, NULL);
sleep(2);
printf("parent about to fork...\n"); pid = fork();
if( 0 == pid )
printf("child returned from fork\n");
else
{
printf("parent returned from fork\n");
wait(NULL);
}
#endif return 0;
}
运行结果:
huangcheng@ubuntu:~$ ./a.out
thread started...
parent about to fork...
preparing locks...
parent unlocking locks...
parent returned from fork
child unlocking locks...
child returned from fork
UNIX环境高级编程——线程和fork的更多相关文章
- UNIX环境高级编程——线程属性
pthread_attr_t 的缺省属性值 属性 值 结果 scope PTHREAD_SCOPE_PROCESS 新线程与进程中的其他线程发生竞争. detachstate PTHREAD_CREA ...
- <UNIX环境高级编程>文件共享及fork函数
UNIX系统支持在不同进程间共享打开文件.内核使用3种数据结构表示打开文件,它们之间的关系决定了文件共享方面一个进程对另一个进程可能产生的影响. 内核维持了3个表,即进程表,文件表和v节点表.具体如下 ...
- UNIX环境高级编程——线程
线程包含了表示进程内执行环境必需的信息,其中包括进程中标示线程的线程ID.一组寄存器值.栈.调度优先级和策略.信号屏蔽字.errno变量以及线程私有数据. 进程的所有信息对该进程的所有线程都是共享的, ...
- Unix 环境高级编程---线程创建、同步、
一下代码主要实现了linux下线程创建的基本方法,这些都是使用默认属性的.以后有机会再探讨自定义属性的情况.主要是为了练习三种基本的线程同步方法:互斥.读写锁以及条件变量. #include < ...
- UNIX环境高级编程——线程和信号
每个线程都有自己的信号屏蔽字,但是信号的处理是进程中所有线程共享的.这意味着尽管单个线程可以阻止某些信号,但当线程修改了与某个信号相关的处理行为以后,所有的线程都必须共享这个处理行为的改变.这样如果一 ...
- UNIX环境高级编程——线程私有数据
线程私有数据(Thread-specific data,TSD):存储和查询与某个线程相关数据的一种机制. 在进程内的所有线程都共享相同的地址空间,即意味着任何声明为静态或外部变量,或在进程堆声明的变 ...
- UNIX环境高级编程——线程属性之分离属性
说到线程的分离状态,我认为,之所以会有这个状态,是因为系统对某些线程的终止状态根本不感兴趣导致的. 我们知道,进程中的线程可以调用: int pthread_join(pthread_t tid, v ...
- UNIX环境高级编程——线程属性之并发度
并发度控制着用户级线程可以映射的内核线程或进程的数目.如果操作系统的实现在内核级的线程和用户级的线程之间保持一对一的映射,那么改变并发度并不会有什么效果,因为所有的用户级线程都可能被调度到.但是,如果 ...
- UNIX环境高级编程——线程同步之互斥锁、读写锁和条件变量(小结)
一.使用互斥锁 1.初始化互斥量 pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;//静态初始化互斥量 int pthread_mutex_init( ...
随机推荐
- NGUI制作可滚动的文本框(摘,如有侵权,联系删除)
NGUI制作可滚动的文本框 1.首先创建一个UI Root 2.选择UI Root右键 Create 选择Scoll View创建. 3.Scroll view的大小是可以调节的,调节为你需要的适当大 ...
- 【实用】【移动端】Retain屏1px解决方案
新浪微博HTML5版 微博的实现方式(rem + 小数px) <meta name="viewport" content="width=device-width,i ...
- jquery easyui datagrid动态改变title的值
title:'<input type="text" id="txtTitle1" style="background:none;border:n ...
- JVM Class字节码之三-使用BCEL改变类属性
使用BCEL动态改变Class内容 之前对Class文件中的常量池,Method的字节码指令进行了说明.JVM Class详解之一JVM Class详解之二 Method字节码指令现在我们开始实际动手 ...
- Python中的str与unicode处理方法
Python中的str与unicode处理方法 2015/03/25 · 基础知识 · 3 评论· Python 分享到:42 原文出处: liuaiqi627 的博客 python2.x中处理 ...
- JSP运行过程 JSP脚本 静态动态包含 jsp指令 jsp内置对象jsp四大作用域 jsp动作元素 EL表达式 JSTL 设计模式 JSP开发模式 EL内置对象
Day38 JSP JSP的运行过程具体如下: (1)客户端发出请求,请求访问JSP文件. (2)JSP容器先将JSP文件转换成一个Java源文件(Java Servlet源程序),在转换过程中,如果 ...
- Java不走弯路教程(前言)
本教程的程序基于Windows开发,所以你需要有一台安装Windows操作系统的电脑. 前言本教程将带你完成Java的初学和WEB框架的开发,学完本教程,你将完成对Java的入门并且对下一步不再迷茫. ...
- Kinect2.0 MultiSourceFrameReader 的 AcquireLatestFrame 方法获取不到帧的解决方案
先把大致要写的东西写一下,手里的活忙完了再完善. 在代码中使用下边的语句,获取Kinect中,colorFrame, depthFrame, bodyIndex三种帧,但是经常会遇到在后边的程序中处理 ...
- 在java中如何使用etcd的v2 和v3 api获取配置,并且对配置的变化进行监控
etcd 和zookeeper 很像,都可以用来做配置管理.并且etcd可以在目前流行的Kubernetes中使用. 但是etcd 提供了v2版本合v3的版本的两种api.我们现在分别来介绍一下这两个 ...
- 修改apache默认主页,重定向404页面
yum 下载apache后默认主页 默认配置文件: vim /etc/httpd/conf/httpd.conf /etc/httpd/conf.d/welcome.conf 跳转页面到 /var/w ...