关于进程和线程的一些思考

从“程序”开始

  • 对于UNIX操作系统,程序是存放在磁盘上的ELF文件(可以通过file命令查看文件类型)
  • 对于windows操作系统,程序是存放在磁盘上的PE文件,其中最常见的是.exe文件。

编译器将高级语言编写成的程序编译成机器码,操作系统将ELF文件读入内存后,ELF文件中的代码段也就是CPU可以执行的机器码(可以通过readelf命令查看ELF文件的代码段内容),CPU从内存中读取机器码并执行。

为进程分配资源

进程产生的标志是:内核为每一个进程都分配了一个task_struct结构体,在task_struct中记录了这个进程所拥有的资源,如全局变量、虚拟内存等,所以说进程是资源分配的最小单位

调度线程

线程是CPU调度的最小单位,也就是说内核进行调度的对象实际上是线程,而进程是负责为线程提供共享资源的

一个进程中的多个线程共享这个进程的资源,但是它们虽然共享同一片虚拟内存,自身却拥有这片虚拟内存中的不同的栈空间

通信方式

由于同一进程中的线程共享资源,所以通信非常方便,直接读写同一块用户态内存即可,但是这必然就涉及到互斥和原子性问题。

而进程要实现通信则需要借助内核和文件,所有的IPC,都是把内核和文件充当交换信息的桥梁。

上下文切换

cpu调度基本的单位是线程,所以在运行不同的线程时,会导致cpu上下文切换,即CPU寄存器和程序计数器的保存和更新。而根据被调度的线程是同一个进程里的还是不同进程里的,又分为线程上下文切换进程上下文切换

CPU上下文切换是需要CPU运行内核代码的,所以过多的cpu上下文切换会导致cpu将大量的时间都用来运行内核代码,导致真正的给用户态线程运行的时间变少。所以一般我们会根据机器的核数来决定进程的线程数量或者子进程数量,避免进行频繁的上下文切换。

由于线程共享进程中的虚拟内存空间,所以线程上下文切换时,不需要更新虚拟内存到物理内存的内存映射表。而进程上下文切换时,由于不同进程虚拟内存的改变,则要更新虚拟内存到物理内存的内存映射表。当内核找不到虚拟内存到物理内存的映射关系时,便会产生缺页中断。所以进程上下文切换后,程序执行更容易产生缺页中断,这也就是进程切换比线程切换对性能影响更大的原因。

怎么理解Linux中的线程是以进程的方式实现的

  • 对于支持线程的操作系统而言,如果一个进程中有N个线程,则存在一个进程描述符,依次轮流指向N个线程。这个进程描述符指明共享资源,包括内存空间和打开的文件。而每一个线程描述它们自己独享的资源。也就是说内核中描述线程的结构体和描述进程的结构体不同
  • 而在Linux中,则有N个task_struct数据结构,只是这些数据结构的某些资源项是共享的(指向同一片内存),某些是独占的。