前言:在redis相关文章中,经常可以看到这句话:“采用单线程,避免了不必要的线程上下文切换和竞争条件"。那么这里的线程上下文具体指的是什么?在阅读《操作系统概念》时正好看到了,就此记录一下我觉得比较重要的部分。
首先,先理解一下程序中上下文的概念: 摘自知乎 --vczh
每一段程序都有很多外部变量。只有像Add这种简单的函数才是没有外部变量的。一旦你的一段程序有了外部变量,这段程序就不完整,不能独立运行。你为了使他们运行,就要给所有的外部变量一个一个写一些值进去。这些值的集合就叫上下文。
(基于Linux)大体上,进程属性分为三组:进程标识,进程环境和进程上下文。
每个进程都有唯一的标识符。当应用程序通过系统调用来触发,修改或等待时,PID用于向操作系统标识本进程。
每个进程必须具有关联的用户ID和一个或多个用户组ID,以便确定进程访问系统资源和文件的权限。
进程个性并不出现在传统的UNIX系统上,但是Linux的每个进程都有一个关联的个性标识符,可以微调某些系统调用的语义。个性主要用于仿真库,以便要求系统调用兼容某些特色UNIX。
每个进程关联文件系统层次结构的一个特定视图,称为命名空间。大多数进程共享一个通用命名空间,从而运行于共享文件系统的层次结构。然而,进程与其子进程可以拥有不同的命名空间,每个都有唯一的文件系统层次结构,如自己的根目录和安装文件系统的集合。
大多数的进程标识符受到进程本身的有限控制。如果进程想要启动新的组或会话,则进程组和会话标识符可以更改。它的凭证在适当安全检查下可以更改。另外,进程的主PID是不可改变的。
进程环境从父进程继承而来,包括两个以null结束的向量:参数向量和环境向量。 · 参数向量(argument vector): 只是简单列出用于调用运行程序的命令行参数;它通常以程序本身的名称开始。 · 环境向量(environment vector): 是以"NAME=VALUE"对的列表,用于关联环境变量与它的文本值。 ————————————————————————————— 几个比较重要的点: ① 环境向量不保存在内核内存中,而是保存在进程自己的用户模式地址空间中,作为进程堆栈顶部地第一项数据。 ② 在新进程被创建时,它的参数和环境向量不会更改。新的子进程会继承父进程的环境。但是,在新程序被调用时,会设置全新的环境。在调用exec()时,必须为新的程序提供环境。
----------------------------正题来了!!!--------------------------------------
通常,进程标识和环境属性在进程创建时设置,并不会改变,直到进程退出。如果需要,进程可以选择改变它的身份的某些方面,或者可以改变它的环境。相对而言,进程上下文是运行程序的任一时刻的状态;它不断变化。
进程上下文最重要的部分就是它的调度上下文,调度程序需要使用这个信息来挂起或重启进程。这个信息包括所有进程寄存器的保存副本。调度上下文也包括了调度优先级和等待传到进程的信号等信息。调度上下文的一个关键部分是进程的内核堆栈,即用于内核模式代码的单独内核内存区域。进程运行时的系统调用和中断会使用这个堆栈。
内核维护的记账信息包括:每个进程正在消耗的资源和进程迄今为止消耗的总资源等。
文件表是个指针数组,指向代表打开文件的内核文件结构。在进行文件I/O系统调用时,进程的文件引用采用一个整数,称为文件描述符(file descriptor, fd),而内核通过fd索引文件表。
文件表列出已经打开的文件,而文件系统上下文用于请求打开新文件。文件系统上下文包括:进程的根目录,当前工作目录和命名空间。
UNIX系统可以传递异步信号到进程,以响应各种外部事件。信号处理程序表定义了响应特定信号的行为。有效行为包括:忽略信号,终止进程并调用进程地址空间的程序。
虚拟内存上下文描述了进程的私有地址空间的全部内容。