前言
一个进程内有多个线程,线程有自己的寄存器,程序计数器,堆栈,状态。但是线程间是没有保护的,可以共享地址空间,打开文件集,子进程,定时器以及相关信号量。为什么没有保护,原因是:不可能,也没必要。不同进程可能来自不同用户,它们之间彼此可能有敌意,用户所持有的资源以进程为单位。
与传统进程一样,线程也拥有运行,阻塞,就绪终止状态,正在运行的线程独占CPU并且活跃。与进程状态切换一致,这里就不介绍了。
每个线程堆栈都有一帧,在该栈帧存放了局部变量和过程调用后的返回地址。
在多线程情况下,进程通常会从当前的单个线程开始,也就是主线程,该线程会调用库函数(thread_create)来创建新线程。一般来说,线程之间是平等的。这里介绍其它库函数:
pthread_exit:线程运行结束时,退出,线程消失。
pthread_join:一个线程可以阻塞等待另一个线程退出。
pthread_yield:允许线程自动放弃CPU让给其它线程。
4. pthread_attr_init:创建并初始化一个线程的属性结构。
5. pthread_attr_destroy:删除一个线程的属性结构。
pthread.h
在用户态实现线程
在用户空间管理线程时,每个进程都会有一个线程表,用来跟踪该进程中的线程。这些表和内核空间中的进程表相似,不过它仅记录线程的属性。
用户线程中,每个进程都有其相关调度算法,可扩展性高,这是因为内核线程需要固定的表格和堆栈空间。
但是,由于用户线程没有时钟中断,导致某线程想要运行时,只能依靠前一个线程主动放弃CPU,所以没有轮转的说法。
在内核中使用线程
当内核支持管理线程时,进程中就没有线程表了,相反,在内核中就有一张线程表,线程想要创建新线程时,通过系统调用来对线程表更新。另外,内核还维护了传统的进程表。
在上述情况下,当一个线程阻塞时,就可以通过系统调用(内核中的线程表)来切换线程了。
在内核回收和创建线程代价是比较大的,所以回收时,一般会将线程标记为不可运行(并不是真正的回收),需要时再启动。用户态线程不需要。
虽然内核线程可以解决很多问题,但不是能解决所有问题。比如信号问题,创建新进程问题等......
混合实现
人们研究出了采用多个用户线程对应一个内核线程的方法,多个用户线程多路复用。
弹出式线程
在分布式系统中,线程经常使用,通常下,服务接受到消息后,该服务所对应的线程会阻塞并receive,但是弹出式线程会创建一个新的线程去处理收到的消息。
在一些OS中,协作的进程可能共享一些彼此都能读写的公共存储区。该存储区可能是一个数据结构,可能是一个共享文件。
审核编辑:刘清
全部0条评论
快来发表一下你的评论吧 !