[Linux]pthread线程清理和资源回收问题
时间:2010-08-17
来源:互联网
问题1、请求撤销线程,而且线程亦被撤销掉,但是注册的线程清理函数没有运行。
现有四个函数分别是,主函数,线程工作函数,线程监视函数,线程清理函数。
其中主函数负责建立工作线程和监视线程,而后为监视线程生产资源。
复制代码
工作线程主要是处理主函数生产的资源。
复制代码
监视函数是为了监视工作线程是否超时,超时则请求撤销该线程,并新建一个工作线程
复制代码
线程清理函数主要是负责当工作线程被撤销时,回收正在使用的资源。
复制代码
在线程超时后,没有看到清理函数输出的内容,用过pstree查看进程信息,发现线程已经取消掉,但是资源未释放内存占用越来越大。这是为什么呢?
问题2、分离属性的线程运行完毕后或者撤消后,什么样的资源是由系统自动回收的?堆分配的资源系统会自动回收么?和joinable的线程在资源处理上有什么分别?看了一些资料,写都不是很详细,麻烦诸位给点详细的资料。
现有四个函数分别是,主函数,线程工作函数,线程监视函数,线程清理函数。
其中主函数负责建立工作线程和监视线程,而后为监视线程生产资源。
- int scheduler_listen(int sock)
- {
- int i ,fd ,ret;
-
- pthread_attr_init(&thread_attr);
- pthread_attr_setstacksize(&thread_attr, 1024*1024);
- pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
- //建立工作线程
- for (i=0; i<SCAN_THREAD_NUM; i++) {
- memset(&thread_param[i], 0x00, sizeof(THREAD_PARAM));
-
- thread_param[i].exec_time = -1;
-
- ret = pthread_create(&(thread_param[i].scan_thread), &thread_attr, loop_scanfile, (void *)&thread_param[i]);
- if (ret != 0) {
- //出错
- return -1;
- }
- }
- //建立监视线程
- pthread_t psd;
- pthread_create(&psd, &thread_attr, status_daemon, NULL);
-
- //block self!
- while(1)
- {
- //生产资源
- }
- puts("exit!");
- return 0;
- }
- void *loop_scanfile(void *param)
- {
-
- struct cancel_param cp;
- //初始化部分
-
- //注册清理函数
- pthread_cleanup_push(thread_cleanup, &cp);
- while(1) {
- //获取资源
- //处理
-
- }//end while(1)
- pthread_cleanup_pop(0);
-
- return NULL;
- }
- void *status_daemon(void *a)
- {
- int i;
- time_t now;
- while(1)
- {
- //休眠
- sleep(5);
-
- time(&now);
- for(i=0; i<SCAN_THREAD_NUM; i++)
- { //检测超时
- if((thread_param[i].exec_time>0) && (now-thread_param[i].exec_time >config.timeout) )
- {
- printf("Scan thread timeout, restart it!\n");
-
- //请求撤销
- pthread_cancel(thread_param[i].scan_thread);
- //新建线程
- if ( pthread_create(&(thread_param[i].scan_thread), NULL, loop_scanfile, (void *)&thread_param[i]) != 0)
- {
- gate_print("%sScan thread recreate failed!",ERRSTR);
- exit(-1);
-
- }
- }
- }
-
- }
- return NULL;
- }
- void thread_cleanup(void *param)
- {
- struct cancel_param *cp = (struct cancel_param*)param;
- puts("Cleaning");
- //清理资源
- }
问题2、分离属性的线程运行完毕后或者撤消后,什么样的资源是由系统自动回收的?堆分配的资源系统会自动回收么?和joinable的线程在资源处理上有什么分别?看了一些资料,写都不是很详细,麻烦诸位给点详细的资料。
作者: davelv 发布时间: 2010-08-17
借楼主的帖提个问题:
线程函数的返回值哪里获得的?
比如
void *test(void *ptr)
{
int a=0;
return((void*)a);
}
怎么获得a的值?pthread_create里面吗?
线程函数的返回值哪里获得的?
比如
void *test(void *ptr)
{
int a=0;
return((void*)a);
}
怎么获得a的值?pthread_create里面吗?
作者: jt_feelcool 发布时间: 2010-08-17
回复 jt_feelcool
使用pthread_join()函数,但是不能用在已分离的线程上,线程默认是可以join的。
使用pthread_join()函数,但是不能用在已分离的线程上,线程默认是可以join的。
作者: davelv 发布时间: 2010-08-17
QUOTE:
回复 jt_feelcool
使用pthread_join()函数,但是不能用在已分离的线程上,线程默认是可以join的 ...
davelv 发表于 2010-08-17 11:42
使用pthread_join()函数,但是不能用在已分离的线程上,线程默认是可以join的 ...
davelv 发表于 2010-08-17 11:42
多谢大侠
作者: jt_feelcool 发布时间: 2010-08-17
回复 davelv
不管哪种属性,堆上申请的必须手工释放,但是如果是分离属性的线程,自身的栈等资源都会自行释放.
不管哪种属性,堆上申请的必须手工释放,但是如果是分离属性的线程,自身的栈等资源都会自行释放.
作者: samlumengjun 发布时间: 2010-08-17
回复 davelv
复制代码
我模拟你的程序,写了测试程序,线程清理函数是执行了的。
一个 pthread_cancel 并不等待线程退出,也就是说这个函数调用后,进程仍然在,这个时候马上创建新线程,并使用这个插槽,相当与新旧线程共用一个插槽,资源泄漏是不是和这个有关。
我的程序里增加了join,cancel之后,等待老线程退出,才创建新的线程。
问题2,我碰到的情况是,如果不是detach的线程,只有join才会回收线程本身的资源,这些不包括分配在堆上的内存。如果不join,且没有detach,则线程自身的资源也不回收,频繁的创建/删除进程,这个资源浪费,也很可观。
- #include <pthread.h>
- #include <stdio.h>
- #include <time.h>
- #include <unistd.h>
-
- #define N 2
-
- struct thread_st {
- pthread_t ptid;
- time_t ctime;
- };
-
- struct thread_st pst[N];
-
- void *loop(void *);
- void *monitor(void *);
-
- int main()
- {
- size_t i;
- for (i = 0; i < N; ++i) {
- pthread_create(&pst[i].ptid, NULL, loop, pst + i);
- pst[i].ctime = time(NULL);
- }
- pthread_t ptid;
- pthread_create(&ptid, NULL, monitor, NULL);
-
- while (1) sleep(10);
-
- return 0;
- }
-
- void fclean(void *p)
- {
- struct thread_st *pst = p;
- printf("%d cleanup, exit\n", (int)pst->ptid);
- }
-
- void *loop(void *p)
- {
- struct thread_st *pst = p;
- pthread_cleanup_push(fclean, p);
- while (1) {
- printf("%d running\n", (int)pst->ptid);
- sleep(1);
- }
- pthread_cleanup_pop(0);
- return 0;
- }
-
- void *monitor(void *p)
- {
- size_t i;
- while (1) {
- for (i = 0; i < N; ++i) {
- if (time(NULL) - pst[i].ctime > 3) {
- pthread_cancel(pst[i].ptid);
- pthread_join(pst[i].ptid, NULL);
- pthread_create(&pst[i].ptid, NULL, loop, pst + i);
- pst[i].ctime = time(NULL);
- }
- }
- sleep(1);
- }
- return 0;
- }
一个 pthread_cancel 并不等待线程退出,也就是说这个函数调用后,进程仍然在,这个时候马上创建新线程,并使用这个插槽,相当与新旧线程共用一个插槽,资源泄漏是不是和这个有关。
我的程序里增加了join,cancel之后,等待老线程退出,才创建新的线程。
问题2,我碰到的情况是,如果不是detach的线程,只有join才会回收线程本身的资源,这些不包括分配在堆上的内存。如果不join,且没有detach,则线程自身的资源也不回收,频繁的创建/删除进程,这个资源浪费,也很可观。
作者: zzyong08 发布时间: 2010-08-17
相关阅读 更多
热门阅读
-
office 2019专业增强版最新2021版激活秘钥/序列号/激活码推荐 附激活工具
阅读:74
-
如何安装mysql8.0
阅读:31
-
Word快速设置标题样式步骤详解
阅读:28
-
20+道必知必会的Vue面试题(附答案解析)
阅读:37
-
HTML如何制作表单
阅读:22
-
百词斩可以改天数吗?当然可以,4个步骤轻松修改天数!
阅读:31
-
ET文件格式和XLS格式文件之间如何转化?
阅读:24
-
react和vue的区别及优缺点是什么
阅读:121
-
支付宝人脸识别如何关闭?
阅读:21
-
腾讯微云怎么修改照片或视频备份路径?
阅读:28