打印
[应用相关]

ST学习笔记

[复制链接]
947|49
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
一、ST简介

ST是一个C语言微线程开源库:http://sourceforge.net/projects/state-threads/

微线程最大的好处就是将传统的EDSM(Event Drive State Machine)异步化多路复用编程(epoll/select等)串行化。通过在一个进程内模拟多个微线程并发,使得异步编程像同步一样简单。但是ST的本质仍然是基于EDSM模型,ST将请求抽象为thread概念,ST的调度器(scheduler)对于用户来说是透明的,不像dispatcher那种将执行状态(execute state)暴露给回调方式。


传统EDSM调度模型

ST调度模型

ST通过setjmp和longjmp来实现微线程调用栈上下文(仅包括寄存器状态)的保存与恢复。而调用栈是通过额外分配堆内存来保存的,并没有与物理进程共享调用栈。


使用特权

评论回复
沙发
花间一壶酒sd|  楼主 | 2021-2-20 18:08 | 只看该作者
二、ST的栈结构介绍
1. // 栈结构

2. typedef struct _st_stack {

3.   _st_clist_t links;

4.   char *vaddr;                /* Base of stack's allocated memory */

5.   int  vaddr_size;            /* Size of stack's allocated memory */

6.   int  stk_size;              /* Size of usable portion of the stack */

7.   char *stk_bottom;           /* Lowest address of stack's usable portion */

8.   char *stk_top;              /* Highest address of stack's usable portion */

9.   void *sp;                   /* Stack pointer from C's point of view */

10. } _st_stack_t;

使用特权

评论回复
板凳
花间一壶酒sd|  楼主 | 2021-2-20 18:14 | 只看该作者
11. //线程结构

12. typedef struct _st_thread {

13.   int state;                  /* Thread's state */

14.   int flags;                  /* Thread's flags */

15.   void *(*start)(void *arg);  /* The start function of the thread */

16.   void *arg;                  /* Argument of the start function */

17.   void *retval;               /* Return value of the start function */

18.   _st_stack_t *stack;      /* Info about thread's stack */

19.   _st_clist_t links;          /* For putting on run/sleep/zombie queue */

20.   _st_clist_t wait_links;     /* For putting on mutex/condvar wait queue */

21.   st_utime_t due;             /* Wakeup time when thread is sleeping */

22.   _st_thread_t *left;         /* For putting in timeout heap */

23.   _st_thread_t *right;      /* -- see docs/timeout_heap.txt for details */

24.   int heap_index;

25.   void **private_data;        /* Per thread private data */

26.   _st_cond_t *term;           /* Termination condition variable for join */

27.   jmp_buf context;            /* Thread's context */

28. } st_thread_t;

使用特权

评论回复
地板
花间一壶酒sd|  楼主 | 2021-2-20 18:17 | 只看该作者

微线程栈结构图

使用特权

评论回复
5
花间一壶酒sd|  楼主 | 2021-2-20 18:19 | 只看该作者
上图是栈分配后的结果,两边是REDZONE使用mprotect保护不被访问(仅debug模式开启),extra是用于开启随机栈地址空间使用的,随机栈地址开启后会调整bottom和top,就是随机的向右边移动一点。应该是用于防止栈溢出攻击。总之,最后使用的,对外提供的接口就是[bottom, top]这个内存区域,[bottom, top]区域又进一步分为:

ptds:微线程的私有数据(private_data),是12个指针(ST_KEYS_MAX指定),参考st_key_create()。

trd:st_thread_t结构本身也是在这个stack中分配的。

pad+align:在trd之后是对齐和pad(_ST_STACK_PAD_SIZE指定)。

sp:微线程实际的栈指针。

st_thread_create函数创建微线程时会初始化sp。微线程栈的分配详情参考_st_stack_new函数。

使用特权

评论回复
6
花间一壶酒sd|  楼主 | 2021-2-20 18:19 | 只看该作者
三、重要函数注释
1)st_thread_create

1. /*

2.  * 创建微线程

3.  * @start微线程start函数

4.  * @arg入口函数参数列表

5.  * @joinablejoinable标记

6.  * @stk_size微线程栈大小

7.  */

8. _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinable, int stk_size)

9. {

10. _st_thread_t *thread;

11. _st_stack_t *stack;

12. void **ptds;

13. char *sp;

14.

使用特权

评论回复
7
花间一壶酒sd|  楼主 | 2021-2-20 18:21 | 只看该作者
15. /* 调整线程栈大小 */

16. if (stk_size == 0)

17. /* 如果stk_size为0,设置为默认大小 */

18. stk_size = ST_DEFAULT_STACK_SIZE;

19. /* 否则调整栈大小为内存页的整数倍 */

20. stk_size = ((stk_size + _ST_PAGE_SIZE - 1) / _ST_PAGE_SIZE) * _ST_PAGE_SIZE;

21. /* 申请占空间并对栈空间结构初始化,参见微线程栈结构图 */

22. stack = _st_stack_new(stk_size);

23. if (!stack)

24. return NULL;

25.

使用特权

评论回复
8
花间一壶酒sd|  楼主 | 2021-2-20 18:22 | 只看该作者
26. sp = stack->stk_top;

27. /* 私有数据指针ptds初始化 */

28. sp = sp - (ST_KEYS_MAX * sizeof(void *));

29. ptds = (void **) sp;

30. /* 线程结构指针初始化初始化 */

31. sp = sp - sizeof(_st_thread_t);

32. thread = (_st_thread_t *) sp;

33.

使用特权

评论回复
9
花间一壶酒sd|  楼主 | 2021-2-20 18:24 | 只看该作者
34. /* 栈实际可用空间64B对齐 */

35. if ((unsigned long)sp & 0x3f)

36. sp = sp - ((unsigned long)sp & 0x3f);

37. /* 栈指针初始化 */

38. stack->sp = sp - _ST_STACK_PAD_SIZE;

39.

使用特权

评论回复
10
花间一壶酒sd|  楼主 | 2021-2-20 18:27 | 只看该作者
40. /* 线程结构初始化和赋值 */

41. memset(thread, 0, sizeof(_st_thread_t));

42. memset(ptds, 0, ST_KEYS_MAX * sizeof(void *));

43.

使用特权

评论回复
11
花间一壶酒sd|  楼主 | 2021-2-20 18:27 | 只看该作者
44. thread->private_data = ptds;

45. thread->stack = stack;

46. thread->start = start;

47. thread->arg = arg;

48.

使用特权

评论回复
12
花间一壶酒sd|  楼主 | 2021-2-20 18:28 | 只看该作者
49. /* 线程上下文初始化

50. *#define _ST_INIT_CONTEXT(_thread, _sp, _main) \

51. *if (MD_SETJMP((_thread)->context))         \

52. *_main();                                 \

53. *(_thread)->context[3] = (long) (_sp);     \

54. * 初始化上下文是MD_SETJMP返回0,此时不会执行入口函数_main(_st_thread_main)

55. * 当下一次调度到该微线程时,从_main(_st_thread_main)继续执行

56. * _st_thread_main的注释见下文

57. */

58. _ST_INIT_CONTEXT(thread, stack->sp, _st_thread_main);

59.   

使用特权

评论回复
13
花间一壶酒sd|  楼主 | 2021-2-20 22:11 | 只看该作者
60. ......

61.   

62. thread->state = _ST_ST_RUNNABLE;/* 设置线程为可运行状态 */

63. _st_active_count++;/* 活动线程数加1,idle线程在做调度时会判断该技术,决定程序是否退出 */

64. _ST_ADD_RUNQ(thread);/* 将线程加入运行队列,等待被调度执行 */

65.

使用特权

评论回复
14
花间一壶酒sd|  楼主 | 2021-2-20 22:12 | 只看该作者
66. return thread;

67. }

使用特权

评论回复
15
花间一壶酒sd|  楼主 | 2021-2-20 22:13 | 只看该作者
2)st_thread_main

1. /*

2.  * 微线程统一入口函数

3. */

4. void _st_thread_main(void)

5. {

6. _st_thread_t *thread = _ST_CURRENT_THREAD();

7. /*

8. * Cap the stack by zeroing out the saved return address register

9. * value. This allows some debugging/profiling tools to know when

10. * to stop unwinding the stack. It's a no-op on most platforms.

11. */

12. MD_CAP_STACK(&thread);

13.

使用特权

评论回复
16
花间一壶酒sd|  楼主 | 2021-2-20 22:14 | 只看该作者
14. /* 调用线程start函数

15. * 如果不想让微线程退出,可以将start函数死循环,

16. * 在IO等待时ST会调用_ST_SWITCH_CONTEXT切换至其他线程运行

17. * 等到IO READY后调度回该线程继续执行

18. */

19. thread->retval = (*thread->start)(thread->arg);

20.

使用特权

评论回复
17
花间一壶酒sd|  楼主 | 2021-2-20 22:15 | 只看该作者
21. /* 然后调用st_thread_exit函数退出微线程 */

22. st_thread_exit(thread->retval);

23. }

使用特权

评论回复
18
花间一壶酒sd|  楼主 | 2021-2-20 22:17 | 只看该作者
3)st_thread_exit微线退出函数

1. /*

2.  * 微线程退出函数

3. */

4. void st_thread_exit(void *retval)

5. {

6. _st_thread_t *thread = _ST_CURRENT_THREAD();

7.

使用特权

评论回复
19
花间一壶酒sd|  楼主 | 2021-2-20 22:18 | 只看该作者
8. thread->retval = retval;

9. /* 释放线程私有数据 */

10. _st_thread_cleanup(thread);

11. /* 活跃线程计数减1 */

12. _st_active_count--;

13. /* 对于joinable线程,推出前需要通知其他线程 */

14. if (thread->term) {

15. /* Put thread on the zombie queue */

16. thread->state = _ST_ST_ZOMBIE;

17. _ST_ADD_ZOMBIEQ(thread);

18.

使用特权

评论回复
20
花间一壶酒sd|  楼主 | 2021-2-20 22:18 | 只看该作者
19. /* Notify on our termination condition variable */

20. st_cond_signal(thread->term);

21.

22. /* Switch context and come back later */

23. _ST_SWITCH_CONTEXT(thread);

24.

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

89

主题

1144

帖子

2

粉丝