关于 pthread
来源:百度文库 编辑:神马文学网 时间:2024/04/25 12:24:14
chengdot
================================
从pthread_cleanup_push()的调用点到pthread_cleanup_pop()之间的程序段中的终止动作
(包括调用pthread_exit()和取消点终止)都将执行pthread_cleanup_push()所指定的清理函数。
================================
请问其中的“取消点终止”是什么意思?
我尝试了以下的 pthread_cancel(),但并不会触发 clean(),这是为什么?
以下是代码:
#include
#include
#include
#include
void clean(void* p)
{
printf("clean()\n");
}
void* thread(void* p)
{
pthread_cleanup_push(clean, NULL);
//===============================
printf("thread sleep\n");
sleep(10);
printf("thread wake...\n");
//===============================
pthread_cleanup_pop(1);
}
int main()
{
pthread_t id;
pthread_create(&id, NULL, thread, NULL);
printf("main sleep\n");
sleep(3);
printf("cancel thread: %u\n", id);
pthread_cancel(id);
return 0;
}
==========================
输出:
thread sleep
main sleep
cancel thread: 3085872016
==========================
在 xxx_push() 和 xxx_pop() 之间唯有调用 pthread_exit() 会触发 clean() 函数,
return 也不会,(异常没有试过, 还不会手动抛出异常);
这是一个老问题了,也看到别人问过(比如: http://bbs.chinaunix.net/viewthread.php?tid=456153)
但在网上一直没有找到正式的回答;
诚邀您共建CU技术主题索引贴| PC采购经济效益如何最佳? | Redhat授权RHCE超低价考试| 《深入理解计算机系统》第2版
yang200218
pthread_cleanup_push() installs the cancellation cleanup handler
routine onto the calling thread's cancellation cleanup stack. This
handler will be popped from the calling thread's cancellation cleanup
stack。
诚邀您共建CU技术主题索引贴| PC采购经济效益如何最佳? | Redhat授权RHCE超低价考试| 《深入理解计算机系统》第2版
new_new_one
顶起来。
首先你必须知道pthread_cleanup_push与pthread_cleanup_pop的目的(作用)是什么。
比如thread1:
执行
pthread_mutex_lock(&mutex);
//一些会阻塞程序运行的调用,比如套接字的accept,等待客户连接
sock = accept(......); //这里是随便找的一个可以阻塞的接口
pthread_mutex_unlock(&mutex);
这个例子中,如果线程1执行accept时,线程会阻塞(也就是等在那里,有客户端连接的时候才返回,或则出现其他故障),线程等待中......
这时候线程2发现线程1等了很久,不赖烦了,他想关掉线程1,于是调用pthread_cancel()或者类似函数,请求线程1立即退出。
这时候线程1仍然在accept等待中,当它收到线程2的cancel信号后,就会从accept中退出,然后终止线程,注意这个时候线程1还没有执行:
pthread_mutex_unlock(&mutex);
也就是说锁资源没有释放,这回造成其他线程的死锁问题。
所以必须在线程接收到cancel后用一种方法来保证异常退出(也就是线程没达到终点)时可以做清理工作(主要是解锁方 面),pthread_cleanup_push与pthread_cleanup_pop就是这样的。
pthread_cleanup_push(some_clean_func,...)
pthread_mutex_lock(&mutex);
//一些会阻塞程序运行的调用,比如套接字的accept,等待客户连接
sock = accept(......); //这里是随便找的一个可以阻塞的接口
pthread_mutex_unlock(&mutex);
pthread_cleanup_pop(0);
return NULL;
上面的代码,如果accept被cancel后线程退出,会自动调用some_clean_func函数,在这个函数中你可以释放锁资源。如果 accept没有被cancel,那么线程继续执行,当pthread_mutex_unlock(&mutex);表示线程自己正确的释放资源 了,而执行pthread_cleanup_pop(0);也就是取消掉前面的some_clean_func函数。接着return线程就正确的结束 了。
不晓得你明白没,通俗点就是:
pthread_cleanup_push注册一个回调函数,如果你的线程在对应的pthread_cleanup_pop之前异常退出(return是 正常退出,其他是异常),那么系统就会执行这个回调函数(回调函数要做什么你自己决定)。但是如果在pthread_cleanup_pop之前没有异常 退出,pthread_cleanup_pop就把对应的回调函数取消了,
关于取消点的解释:
比如你执行:
printf("thread sleep\n");
sleep(10);
printf("thread wake...\n");
在sleep函数中,线程睡眠,结果收到cancel信号,这时候线程从sleep中醒来,但是线程不会立刻退出。这是应为pthread与C库方面的原 因(具体是啥我也不清楚),pthread的建议是,如果一个函数是阻塞的,那么你必须在这个函数前 后建立取消点,比如:
printf("thread sleep\n");
pthread_testcancel();
sleep(10);
pthread_testcancel();
printf("thread wake...\n");
这样,就添加了两个取消掉。在执行到pthread_testcancel的位置时,线程才可能响应cancel退出进程。
额外的知识:
对于cancel信号,线程有两种方法: 忽略,和响应。默认是响应
接收到cancel信号,线程有两种处理类型: 立即响应 和 延迟响应(在最近的取消点响应),默认是延迟响应
诚邀您共建CU技术主题索引贴| PC采购经济效益如何最佳? | Redhat授权RHCE超低价考试| 《深入理解计算机系统》第2版
new_new_one
printf("clean()\n");
这句的答应结果,是因为你的主线程在执行pthread_cancel后就退出了,这导致进程退出。
换句话说就是你的:printf("clean()\n");还没来得及执行,进程就释放了资源。
你在执行pthread_cancel后在加上一个sleep就行了
- 发短消息
- 加为好友
chengdot 当前离线
- UID
- 22843309
- 帖子
- 48
- 精华
- 0
- 积分
- 72
- 可用积分
- 72
- 信誉积分
- 100
- 专家积分
- 0
- 空间积分
- 0
- 阅读权限
- 10
- 在线时间
- 101 小时
- 注册时间
- 2009-11-10
- 最 后登录
- 2010-10-09
侠客
- 帖子
- 48
- 主题
- 8
- 精华
- 0
- 可用积分
- 72
- 专家积分
- 0
- 在线时间
- 101 小时
- 注册时间
- 2009-11-10
- 最 后登录
- 2010-10-09
状态:...当前离线...
[微博] [博客] [短信]
[倒序看帖] 1楼 发表于 2009-11-13 11:59 | 只看该作者关于 pthread_cleanup_push 有如下描述:
================================
从pthread_cleanup_push()的调用点到pthread_cleanup_pop()之间的程序段中的终止动作
(包括调用pthread_exit()和取消点终止)都将执行pthread_cleanup_push()所指定的清理函数。
================================
请问其中的“取消点终止”是什么意思?
我尝试了以下的 pthread_cancel(),但并不会触发 clean(),这是为什么?
以下是代码:
#include
#include
#include
#include
void clean(void* p)
{
printf("clean()\n");
}
void* thread(void* p)
{
pthread_cleanup_push(clean, NULL);
//===============================
printf("thread sleep\n");
sleep(10);
printf("thread wake...\n");
//===============================
pthread_cleanup_pop(1);
}
int main()
{
pthread_t id;
pthread_create(&id, NULL, thread, NULL);
printf("main sleep\n");
sleep(3);
printf("cancel thread: %u\n", id);
pthread_cancel(id);
return 0;
}
==========================
输出:
thread sleep
main sleep
cancel thread: 3085872016
==========================
在 xxx_push() 和 xxx_pop() 之间唯有调用 pthread_exit() 会触发 clean() 函数,
return 也不会,(异常没有试过, 还不会手动抛出异常);
这是一个老问题了,也看到别人问过(比如: http://bbs.chinaunix.net/viewthread.php?tid=456153)
但在网上一直没有找到正式的回答;
诚邀您共建CU技术主题索引贴| PC采购经济效益如何最佳? | Redhat授权RHCE超低价考试| 《深入理解计算机系统》第2版
yang200218
- 发短消息
- 加为好友
yang200218 当前离线
- UID
- 12644448
- 帖子
- 132
- 精华
- 0
- 积分
- 217
- 可用积分
- 217
- 信誉积分
- 0
- 专家积分
- 0
- 空间积分
- 0
- 阅读权限
- 20
- 在线时间
- 199 小时
- 注册时间
- 2008-04-11
- 最 后登录
- 2010-10-09
圣骑士
- 帖子
- 132
- 主题
- 11
- 精华
- 0
- 可用积分
- 217
- 专家积分
- 0
- 在线时间
- 199 小时
- 注册时间
- 2008-04-11
- 最 后登录
- 2010-10-09
状态:...当前离线...
[微博] [博客] [短信]
2楼 发表于 2010-01-13 16:08 | 只看该作者
回复 #1 chengdot 的帖子
我的理解是 pthread_cancel() 应该在thread函数中调用,pthread_cleanup_push() installs the cancellation cleanup handler
routine onto the calling thread's cancellation cleanup stack. This
handler will be popped from the calling thread's cancellation cleanup
stack。
诚邀您共建CU技术主题索引贴| PC采购经济效益如何最佳? | Redhat授权RHCE超低价考试| 《深入理解计算机系统》第2版
new_new_one
- 发短消息
- 加为好友
new_new_one 当前离线
- UID
- 22315117
- 帖子
- 54
- 精华
- 0
- 积分
- 92
- 可用积分
- 92
- 信誉积分
- 100
- 专家积分
- 0
- 空间积分
- 0
- 阅读权限
- 10
- 在线时间
- 23 小时
- 注册时间
- 2009-08-10
- 最 后登录
- 2010-11-03
骑士
- 帖子
- 54
- 主题
- 16
- 精华
- 0
- 可用积分
- 92
- 专家积分
- 0
- 在线时间
- 23 小时
- 注册时间
- 2009-08-10
- 最 后登录
- 2010-11-03
状态:...当前离线...
[微博] [博客] [短信]
6楼 发表于 2010-09-15 09:13 | 只看该作者本帖最后由 new_new_one 于 2010-09-15 09:26 编辑
顶起来。
首先你必须知道pthread_cleanup_push与pthread_cleanup_pop的目的(作用)是什么。
比如thread1:
执行
pthread_mutex_lock(&mutex);
//一些会阻塞程序运行的调用,比如套接字的accept,等待客户连接
sock = accept(......); //这里是随便找的一个可以阻塞的接口
pthread_mutex_unlock(&mutex);
这个例子中,如果线程1执行accept时,线程会阻塞(也就是等在那里,有客户端连接的时候才返回,或则出现其他故障),线程等待中......
这时候线程2发现线程1等了很久,不赖烦了,他想关掉线程1,于是调用pthread_cancel()或者类似函数,请求线程1立即退出。
这时候线程1仍然在accept等待中,当它收到线程2的cancel信号后,就会从accept中退出,然后终止线程,注意这个时候线程1还没有执行:
pthread_mutex_unlock(&mutex);
也就是说锁资源没有释放,这回造成其他线程的死锁问题。
所以必须在线程接收到cancel后用一种方法来保证异常退出(也就是线程没达到终点)时可以做清理工作(主要是解锁方 面),pthread_cleanup_push与pthread_cleanup_pop就是这样的。
pthread_cleanup_push(some_clean_func,...)
pthread_mutex_lock(&mutex);
//一些会阻塞程序运行的调用,比如套接字的accept,等待客户连接
sock = accept(......); //这里是随便找的一个可以阻塞的接口
pthread_mutex_unlock(&mutex);
pthread_cleanup_pop(0);
return NULL;
上面的代码,如果accept被cancel后线程退出,会自动调用some_clean_func函数,在这个函数中你可以释放锁资源。如果 accept没有被cancel,那么线程继续执行,当pthread_mutex_unlock(&mutex);表示线程自己正确的释放资源 了,而执行pthread_cleanup_pop(0);也就是取消掉前面的some_clean_func函数。接着return线程就正确的结束 了。
不晓得你明白没,通俗点就是:
pthread_cleanup_push注册一个回调函数,如果你的线程在对应的pthread_cleanup_pop之前异常退出(return是 正常退出,其他是异常),那么系统就会执行这个回调函数(回调函数要做什么你自己决定)。但是如果在pthread_cleanup_pop之前没有异常 退出,pthread_cleanup_pop就把对应的回调函数取消了,
关于取消点的解释:
比如你执行:
printf("thread sleep\n");
sleep(10);
printf("thread wake...\n");
在sleep函数中,线程睡眠,结果收到cancel信号,这时候线程从sleep中醒来,但是线程不会立刻退出。这是应为pthread与C库方面的原 因(具体是啥我也不清楚),pthread的建议是,如果一个函数是阻塞的,那么你必须在这个函数前 后建立取消点,比如:
printf("thread sleep\n");
pthread_testcancel();
sleep(10);
pthread_testcancel();
printf("thread wake...\n");
这样,就添加了两个取消掉。在执行到pthread_testcancel的位置时,线程才可能响应cancel退出进程。
额外的知识:
对于cancel信号,线程有两种方法: 忽略,和响应。默认是响应
接收到cancel信号,线程有两种处理类型: 立即响应 和 延迟响应(在最近的取消点响应),默认是延迟响应
诚邀您共建CU技术主题索引贴| PC采购经济效益如何最佳? | Redhat授权RHCE超低价考试| 《深入理解计算机系统》第2版
new_new_one
- 发短消息
- 加为好友
new_new_one 当前离线
- UID
- 22315117
- 帖子
- 54
- 精华
- 0
- 积分
- 92
- 可用积分
- 92
- 信誉积分
- 100
- 专家积分
- 0
- 空间积分
- 0
- 阅读权限
- 10
- 在线时间
- 23 小时
- 注册时间
- 2009-08-10
- 最 后登录
- 2010-11-03
骑士
- 帖子
- 54
- 主题
- 16
- 精华
- 0
- 可用积分
- 92
- 专家积分
- 0
- 在线时间
- 23 小时
- 注册时间
- 2009-08-10
- 最 后登录
- 2010-11-03
状态:...当前离线...
[微博] [博客] [短信]
7楼 发表于 2010-09-15 09:30 | 只看该作者至于你的代码例子中为什么没有看到:
printf("clean()\n");
这句的答应结果,是因为你的主线程在执行pthread_cancel后就退出了,这导致进程退出。
换句话说就是你的:printf("clean()\n");还没来得及执行,进程就释放了资源。
你在执行pthread_cancel后在加上一个sleep就行了
关于 pthread
pcap libnet pthread
pthread高级部分整理
多线程pthread编程
pthread线程间通信之条件变量
关于.......
关于...
关于......
关于......
关于......
关于。。。
关于.........
关于。。。。。
关于关于金钱
关于初恋,关于爱情
关于爱情,关于人生
关于青春关于爱
关于爱情、关于伴侣、关于承诺、关于人生、关于友情、关于微笑、关于生活、关于幸福
关于爱情、关于伴侣、关于承诺、关于人生、关于友情、关于微笑、关于生活、关于幸福、
关于爱情、关于伴侣、关于承诺、关于人生、关于友情、关于微笑、关于生活、关于幸福
关于适当,关于平衡!
关于适当,关于平衡!
关于爱情 关于伴侣关于承诺 关于人生 关于友情关于微笑 关于生活 关于幸福
关于星星 关于我们