当前位置:   article > 正文

Linux系统线程创建的过程_使用linux标准线程库实现线程编程的主要过程

使用linux标准线程库实现线程编程的主要过程

推荐使用线程的理由有哪些

  1. 线程共享进程的所有资源,如mm_struct,所以线程的创建比进程更快;
  2. 由于同一个进程的线程间共享mm_struct,所以线程间的数据传输效率会更高,不需要依赖什么通信机制;
  3. 一个进程中,可以实现程序真正的并行;
  4. 多CPU系统中,多线程可以真正的并发执行,提高资源利用率

进程和线程的关系:

进程 = = 资源管理 + 线程

线程可以访问的数据

  1. 代码,.text
  2. 线程栈,从进程的堆上开辟,大小默认为 8M
  3. 全局数据
  4. 线程私有数据,thread_local,对应linux上的接口分别是,pthread_key_create(),ptread_setspecific(),pthread_getspecific()以及pthread_key_delete()
#ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15276
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15276
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

进程维护线程栈空间

使用两个链表来管理这些线程栈:

  1. stack_used 维护还没有退出的线程的线程栈
  2. stack_cache 维护已经退出的线程的线程栈。一般退出的线程的线程栈并不马上销毁,而是缓存在堆中,等下次有新的线程启动了,直接拿来使用即可,不需要重新的申请分配。

Linux系统创建线程的过程

  1. 用户程序调用Linux库函数,pthread_create()

  2. 试图根据设置用户态的栈的大小从stack_cache找出合适大小的线程栈,如果有,设置为线程栈,如果没有则从堆中申请指定大小的空间作为线程栈;

  3. 创建一个pthread实例,将这个实例放在线程栈的栈低位置,pthread中存放可当前线程的数据,如线程的私有数据,栈的大小,需要执行的函数等。

  4. 主线程调用create_thread(),create_thread()将调用clone()产生系统调用,陷入内核

  5. 将主线程的寄存器信息保存在主线程内核栈中,然后调用sys_clone()

  6. 紧接着调用do_fork():

    创建task_struct,以及对应的内核栈

    不需要复制进程的task_struct,共享进程的task_struct,类似于浅拷贝

  7. 维护亲缘关系:

    tgid 所属进程的pid

    pid 自己的进程id

如果tgid==pid,那么表示当前task是一个进程,如果tgid!=pid,表示当前task是一个线程。

  1. 将该线程的task_struct加入task_struct的链表队列中,返回用户空间

这里调用clone()前,进入内核态前,保存的是主线程的栈和指令指针,按照一般的系统调用来看,
返回用户态后,恢复用户态的执行后,应该是恢复主线程的状态。但是这里clone()与一般的系统调用
不一样,clone()返回后,恢复的栈是刚刚创建的线程的栈,栈顶指针等都是指向刚刚创建的线程的栈。

  1. 调用start_thread(),指向线程函数;
  2. 直到线程结束,将线程栈归还给stack_cache.

小结

线程的创建是用户空间和内核空间共同配合完成的,上述过程中前三部都是发生在用户态,旨在产生一个用户态的thread实例,后面的步骤发生在内核态,旨在产生一个内核态的thread实例,将用户态和内核态的thread实例一一对应,实际上就是一对一的线程模型。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/936420
推荐阅读
相关标签
  

闽ICP备14008679号