美文网首页
state thread库阅读笔记(二)

state thread库阅读笔记(二)

作者: hijiang | 来源:发表于2019-05-06 23:57 被阅读0次

    现在我们从st_init函数开始看起,
    首先,它初始化了一个内部的事件系统,
    1、通过st_set_eventsys,设置了一个全局变量_st_eventsys,而我们一般都使用epoll,所以这个对象指向了_st_epoll_eventsys;
    static _st_eventsys_t _st_epoll_eventsys = {
    "epoll",
    ST_EVENTSYS_ALT,
    _st_epoll_init,
    _st_epoll_dispatch,
    _st_epoll_pollset_add,
    _st_epoll_pollset_del,
    _st_epoll_fd_new,
    _st_epoll_fd_close,
    _st_epoll_fd_getlimit
    };
    2、接着调用_st_io_init:忽略SIGPIPE信号,获取系统打开文件最大限制,存入全局变量_st_osfd_limit中;
    3、初始化_st_this_vp全局变量,并初始化其run_q,io_q,zombie_q链表【也就是协程链表,使用了C语言的通用列表方式,我们就不深究通用链表的设计,要了解查看其它相关资料即可】
    4、调用:(*_st_eventsys->init)(),初始化事件系统,也就是_st_epoll_init;
    它主要初始化了_st_epoll_data全局变量,这个变量主要包括:
    epfd:epoll句柄;
    fd_hint:epoll的最大文件数量
    fd_data_size:等于fd_hint;
    fd_data:初始化未一个fd_data_size大小的数组,每个数组元素里面存着当前文件句柄的读引用数量,写引用数量,执行引用数量及当前文件句柄存着的事件【相当于记录了文件句柄的状态信息】
    evtlist_size:等于fd_hint;
    evtlist:就是epoll_event结构的数组,数组大小也就是fd_data_size了;
    5、
    _st_this_vp.pagesize = getpagesize();//设置一个内存页的大小
    _st_this_vp.last_clock = st_utime();//设置上次时钟
    6、初始化idle协程
    _st_this_vp.idle_thread = st_thread_create(_st_idle_thread_start, NULL, 0, 0);
    st_thread_create:
    a、首先创建一个栈使用的内存,通过_st_stack_new返回一个_st_stack_t对象:
    typedef struct _st_stack {
    _st_clist_t links;
    char vaddr; / Base of stack's allocated memory /
    int vaddr_size; /
    Size of stack's allocated memory /
    int stk_size; /
    Size of usable portion of the stack */
    char stk_bottom; / Lowest address of stack's usable portion */
    char stk_top; / Highest address of stack's usable portion */
    void sp; / Stack pointer from C's point of view */

    ifdef ia64

    void bsp; / Register stack backing store pointer */

    endif

    } _st_stack_t;
    栈大小一般为64kB或者128kB,根据系统不同而有所差异,这里的vaddr就是通过malloc出来的栈空间,一般上就是通过malloc来分配的空间;而stk_bottom会跳过一个REDZONE区域,应该是为了避免栈间冲突之类的设计吧,把栈底一部分空间不用;另外,为了高效分配,会为空闲的栈做一个空闲链表,应该是协程销毁就归还到空闲链表里面吧;
    b、初始化好栈后,将sp指针初始化指向栈的中间位置;bsp也指向那里,然后bsp又做了下对齐,并上移了4095字节,好像是为了和下面一半空间有段空白间隔;然后栈的下半部分:sp = sp - (ST_KEYS_MAX * sizeof(void ));,预留16个void的空间【ptds = (void *) sp;】真讨厌这种缩写,完全看不出ptds什么意思,好像是16个void都是存的私有数据,所以这里要指向下;然后
    sp = sp - sizeof(_st_thread_t);
    thread = (_st_thread_t *) sp;,预留_st_thread_t的存储空间;
    接下来sp又做了64字节对齐,并且空出来4095字节:stack->sp = sp - _ST_STACK_PAD_SIZE;
    接着,初始化:
    memset(thread, 0, sizeof(_st_thread_t));
    memset(ptds, 0, ST_KEYS_MAX * sizeof(void *));
    thread->private_data = ptds;//好吧,ptds,private data,实在让人想不通为什么不在前面命名直接叫private_data_arr之类的;
    thread->stack = stack;//栈
    thread->start = start;//协程开始函数
    thread->arg = arg;//参数

    c、栈就初始化好了,根据英文注解:
    /*

    • The stack segment is split in the middle. The upper half is used
    • as backing store for the register stack which grows upward.
    • The lower half is used for the traditional memory stack which
    • grows downward. Both stacks start in the middle and grow outward
    • from each other.
      */
      stack内存段被一分为二,上半部分用作注册栈bsp(什么意思?),下半部分用作普通的内存栈,也就是C语言用的栈;
      7、将idle_thread从run_q中剔除,然后创建一个叫“基础的”线程:
      thread = (_st_thread_t *) calloc(1, sizeof(_st_thread_t) + (ST_KEYS_MAX * sizeof(void *)));
      if (!thread)
      return -1;
      thread->private_data = (void **) (thread + 1);//刚好指向ST_KEYS_MAX的 dif
      thread->state = _ST_ST_RUNNING;
      thread->flags = _ST_FL_PRIMORDIAL;
      _ST_SET_CURRENT_THREAD(thread);
      _st_active_count++;
      又创建了一个没有start(函数地址)的线程?这是干嘛?
      然后就返回0了;
      至此st_init完成;

    相关文章

      网友评论

          本文标题:state thread库阅读笔记(二)

          本文链接:https://www.haomeiwen.com/subject/ejpjoqtx.html