免费注册 查看新帖 |

ChinaUnix.net

  平台 论坛 博客 文库 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
最近访问板块 发新帖
查看: 1832 | 回复: 3

[C] 通过clone 创造线程, 怎么在线程退出后回收栈空间 [复制链接]

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
发表于 2017-11-30 19:36 |显示全部楼层




以前似乎看到过, 多年不看给忘了, 比如如下代码, 旧找不到能回收栈内存的地方, 关键是syscall(__NR_exit, 0); 不返回了, 如果在之前回收, 偏偏 syscall 又是个函数,函数调用又会写什么返回地址之类的在栈上.
  
ps: 这还真不是写着玩, 不用 pthread 代替, 主要是我想在某个线程里执行外部脚本, 又怕脚本干坏事, 想着 seteuid 临时限制权限, 偏偏 posix 规定, 一个线程这么干了, 影响进程内所有线程, 所以只好自己做线程了
  
static int childFunc(void* arg)
{
     thread_t* thead = (thread_t *) arg;
     thead->func(thead->arg);
     syscall(__NR_exit, 0);
     return 0;
}
  
int mythread_create(pthread_t* tid, void*, void* (*func) (void*), void* arg)
{
     thread_t* thead = (thread_t *) malloc(sizeof(thread_t) + STACK_SIZE);
     if (thead == NULL) {
         return ENOMEM;
     }
     char* stack = (char *) (thead + 1) + STACK_SIZE;
     thead->arg = arg;
     thead->func = func;
  
     pid_t pid = clone(childFunc, stack, CLONE_FILES | CLONE_FS | CLONE_VM |
                       CLONE_IO | CLONE_PARENT | CLONE_SIGHAND | CLONE_SYSVSEM | CLONE_THREAD, thead);
     if (pid == -1) {
         return errno;
     }
     return 0;
}
  

论坛徽章:
43
15-16赛季CBA联赛之四川
日期:2018-10-13 23:26:5015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:36程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
发表于 2017-11-30 22:05 |显示全部楼层
别的不说,你为毛不开个进程跑脚本?

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
发表于 2017-12-01 13:27 |显示全部楼层
本帖最后由 zylthinking 于 2017-12-01 13:28 编辑

这样最简单啊, 不用把脚本写到磁盘上去, 也不用部署还要记得装个脚本解释器, 也不用那一套罗嗦的进程间交互
最后这么干了, 管他呢, 看样子应该问题不大
  1. #include "macro.h"
  2. #include "zyl.h"
  3. #include "list_head.h"
  4. #include <stdlib.h>
  5. #include <sched.h>
  6. #include <errno.h>
  7. #include <unistd.h>
  8. #include <syscall.h>
  9. #define STACK_SIZE (8 * 1024 * 1024)

  10. typedef struct {
  11.     list_head entry;
  12.     void* (*func) (void*);
  13.     void* arg;
  14. } thread_t;

  15. static lock_t lck = lock_initial;
  16. static list_head head = LIST_HEAD_INIT(head);

  17. static thread_t* stack_alloc()
  18. {
  19.     thread_t* thead = NULL;
  20.     lock(&lck);
  21.     if (!list_empty(&head)) {
  22.         list_head* ent = head.next;
  23.         list_del(ent);
  24.         thead = list_entry(ent, thread_t, entry);
  25.     }
  26.     unlock(&lck);

  27.     if (thead == NULL) {
  28.         thead = (thread_t *) malloc(sizeof(thread_t) + STACK_SIZE);
  29.     }
  30.     return thead;
  31. }

  32. static int child(void* arg)
  33. {
  34.     thread_t* thead = (thread_t *) arg;
  35.     thead->func(thead->arg);

  36.     lock(&lck);
  37.     while (!list_empty(&head)) {
  38.         list_head* ent = head.next;
  39.         list_del(ent);
  40.         thread_t* ptr = list_entry(ent, thread_t, entry);
  41.         free(ptr);
  42.     }
  43.     list_add(&thead->entry, &head);
  44.     unlock(&lck);
  45.     __asm__(
  46.         "movq $" str(__NR_exit) ", %rax\n"
  47.         "movq $0, %rdi\n"
  48.         "syscall\n"
  49.     );
  50.     return 0;
  51. }

  52. int mythread_create(void* (*func) (void*), void* arg)
  53. {
  54.     thread_t* thead = stack_alloc();
  55.     if (thead == NULL) {
  56.         return ENOMEM;
  57.     }
  58.     char* stack = (char *) (thead + 1) + STACK_SIZE;
  59.     thead->arg = arg;
  60.     thead->func = func;

  61.     pid_t pid = clone(child, stack, CLONE_FILES | CLONE_FS | CLONE_VM |
  62.                       CLONE_IO | CLONE_PARENT | CLONE_SIGHAND | CLONE_SYSVSEM | CLONE_THREAD, thead);
  63.     if (pid == -1) {
  64.         free(thead);
  65.         return errno;
  66.     }
  67.     return 0;
  68. }
复制代码


论坛徽章:
33
荣誉会员
日期:2011-11-23 16:44:17天秤座
日期:2014-08-26 16:18:20天秤座
日期:2014-08-29 10:12:18丑牛
日期:2014-08-29 16:06:45丑牛
日期:2014-09-03 10:28:58射手座
日期:2014-09-03 16:01:17寅虎
日期:2014-09-11 14:24:21天蝎座
日期:2014-09-17 08:33:55IT运维版块每日发帖之星
日期:2016-04-17 06:23:27操作系统版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-24 06:20:0015-16赛季CBA联赛之天津
日期:2016-05-06 12:46:59
发表于 2017-12-01 18:51 |显示全部楼层
以我对线程的理解, 线程应该没有自己的内存管理,是跟进程共用的内存。当然,我不知道线种自己申请的内存,是不是最后也算在进程里。

另外, 2楼说的对。
楼主这样是在给自己挖坑。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

数据风云,十年变迁
DTCC 第十届中国数据库技术大会已启航!

2019年5月8日~5月10日,由IT168旗下ITPUB企业社区平台主办的第十届中国数据库技术大会(DTCC2019),将在北京隆重召开。大会将邀请百余位行业专家,就热点技术话题进行分享,是广大数据领域从业人士的又一次年度盛会和交流平台。与SACC2018类似,本届大会将采用“3+2”模式:3天传统技术演讲+2天深度主题培训。大会不仅提供超100场的主题演讲,还会提供连续2天的深度课程培训,深化数据领域的项目落地实践方案。
DTCC2019,一场值得期待的数据技术盛会,殷切地希望您报名参与!

活动入口>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP