1、用户线程、内核线程
- 用户线程
程序员需要自己实现线程的数据结构、创建销毁和调度维护。也就相当于需要实现一个自己的线程调度内核。
-
内核线程
程序员直接使用操作系统中已经实现的线程,而线程的创建、销毁、调度和维护,都是靠操作系统(准确的说是内核)来实现,程序员只需要使用系统调用。
jdk1.2之前版本需要程序员自己实现,而之后的版本调用操作系统提供的相关接口。
2、用户态、内核态
用户态和内核态是操作系统的两种运行级别,若线程处于用户态,则其访问资源受限,而处于内核态,则可访问计算机任何资源。注意模态切换
3、内核栈
创建进程时,操作系统会为其分配相应的堆栈等资源。每个进程都有两个栈,用户栈与内存栈(不同进程共享内核空间)。当进程处于用户空间时,CPU堆栈指针寄存器的内容是用户栈地址,而当进程中断或系统调用陷入内核态时,CPU堆栈指针寄存器里保存的是内核空间地址。
当进程陷入内核态时,进程所使用的堆栈也要从用户栈转到内核栈。进程陷入到内核态后,先把用户态堆栈的地址保存在内核栈之中,然后设置堆栈指针寄存器的内容为内核栈的地址,这样完成用户栈向内核栈的转换;当进程从内核态恢复到用户态之后时,在内核态之后的最后将保存在内核栈里面的用户栈的地址恢复到堆栈指针寄存器即可。这样就实现了用户栈和内核栈的互转。
从内核转到用户态时,用户栈的地址是在陷入内核的时候保存在内核栈里面的,但是在陷入内核的时候,如何知道内核栈的地址?关键在进程从用户态转到内核态的时候,进程的内核栈总是空的。这是因为当进程在用户态运行时,使用的用户栈,当进程陷入到内核态时,内核保存进程在内核态运行的相关信息,但是一旦进程返回到用户态后,内核栈中保存的信息无效,会全部恢复,因此每次进程从用户态陷入内核的时候得到的内核栈都是空的。所以在进程陷入内核的时候,直接把内核栈的栈顶地址给堆栈指针寄存器就可以了。
4、其他
- 用户级线程有自己调度算法,线程切换在用户空间,并在用户空间保存上下文。