Why?-------为了限制不同的程序之间的访问能力,防止它们获取别的程序的内存数据,或者获取外围设备的数据并发送到网络,将CPU划分出两个等级---用户态和内核态

两种运行级别,用于区分不同程序的不同权力。

  如果一个应用程序运行在内核态,表明它可以访问到更多的资源,几乎可以访问计算机的任何资源。

  如果一个应用程序运行在用户态,表明其访问资源将受到很多限制

内核态:CPU可以访问内存中的所有设备,包括外围设备,如硬盘、网卡;CPU也可以将自己从一个程序切换到另一个程序

用户态:只能受限地访问内存,且不允许访问外围设备,占用CPU的能力被剥夺,CPU资源可以被其它程序获取

所有程序的运行都是在用户态的,但有时候需要做一些内核态的事情(从硬盘读取数据、或者从键盘输入数据),这些事情的实现必须依赖操作系统,此时,程序就需要向操作系统请求

系统调用机制,在CPU的实现称为陷阱指令

(1)用户态程序将一些数据值放到寄存器中,或者使用参数创建一个堆栈,用来表明这是需要操作系统提供的服务

(2)用户态程序执行陷阱指令

(3)CPU切换到内核态,并跳到位于内存中指定位置的指令,这些指令时操作系统的一部分,他们具有内存保护,不可以被用户态程序访问

(4)这些指令称之为陷阱(trap)或者系统调用处理器,他们会读取程序放入内存的数据参数,并执行程序请求的服务

(5)系统调用完成之后,操作系统会重置CPU为用户态并返回系统调用的结果

内核栈和用户栈

  内核在创建进程的时候,会为进程创建两个栈,内核栈和用户栈。 用户栈存在于用户空间,内核栈存在于内核空间。

    当进程在用户空间运行时,使用用户栈;当进程在内核空间运行时,使用内核栈。

  每个进程通过系统调用或者发生异常进入内核;内核空间为所有进程共享

进程的内核态和用户态

  进程通常都运行在用户态,在用户态使用CPU和内存完成一些事情,但是,当进程需要对硬件进行操作(如读取磁盘文件、发送网络数据)的时候,就需要切换到内核态,在内核态,进程将拥有更多的权限来控制整个计算机,在内核态完成任务之后,进程又切换回用户态。

  设置内核态和用户态的主要目的是为了安全,是程序的两种运行级别,想要对操作系统底层进行操作,就必须切换到内核态,不必担心应用程序对硬件进行非法操作。

用户态切换到内核态

  (1)系统调用

  (2)异常

  (3)外围设备中断

用户线程和内核线程

  用户线程:不需要内核支持,在用户程序中实现的线程,不依赖于操作系统的核心,应用程序利用县城库提供的创建、同步、管理和调度线程的函数来控制用户线程。不需要进行用户态和内核态的切换,开销小。操作系统并不知道多线程的存在。一个线程阻塞将使得整个进程阻塞。

  内核线程:由操作系统内核创建和销毁线程,内核维护进程及线程的上下文信息以及线程的切换。一个内核线程由于I/O操作而阻塞,不会影响其他线程的运行。

  区别:

  (1)操作系统内核是否能感知到线程的存在

  (2)线程的创建、销毁、调度是否需要操作系统内核支持

  (3)用户级线程在执行系统调用指令时,会导致其所属的进程被中断,而内核线程在执行系统调用指令时,只导致该线程被中断

  (4)在只有用户级线程的系统内,CPU调度以进程为单位,处于运行状态的进程中的多个线程由应用程序控制线程轮换执行;

      在有内核线程的系统内,CPU调度以线程为基本单位,由OS的线程调度负责线程的调度