Linux

2019/06/02

进程管理

进程的创建

linux通过fork方法创建一个新的进程,新进程为当前进程的子进程。子进程在创建时会拷贝父进程的大部分内容,会了提高进程创建速度,子进程只拷贝引用,等实际要写的时候,才完整拷贝内容到子进程空间,这叫做写时拷贝。

linux进程的存储结构为进程描述符,进程创建后会分配一个唯一的进程标识pid。linux中所有进程的最终父进程为init进程,系统启动时候创建的第一个进程。

进程上下文

进程上下文:进程执行系统调用的时候,从用户态切换到内核态,内核此时的执行环境就表示进程的上下文中。

线程

linux中没有线程的概念,没有单独提供一个创建线程的方法,要想创建线程使用的也是fork方法。这里先解释下线程和进程的关系。

linux中的进程表示一个执行的程序的,还包括了执行时的资源、状态、代码等一个统称。线程是在进程中活动的对象,每个线程都有一个独立的程序计数器、栈和寄存器。内核调度的对象是线程,而不是进程,每个进程内至少有一个线程。进程内的多个线程共享进程内的资源。

linux使用fork创建线程,需要设置共享的资源,比如地址空间、文件系统资源、文件描述符和信号处理程序等,这样新创建的线程就可以共享父进程资源。

进程调度

linux进程的调用采用的是抢占式调度,即调度程序来决定进程什么时候执行以及执行多久。进程的执行时间是预先分配好的,叫做进程的时间片。

非抢占式调度,即除非进程自己主动让出CPU,否者它会一直执行。

CPU密集型任务和I/O密集型任务

I/O密集型任务,这里的I/O指的是IO事件,比如磁盘、网络、外设的I/O事件。进程的大部分时间都用来提交I/O求或者等待I/O请求。对于这类型的任务,CPU是空闲的。

CPU密集型任务,进程的大部分时间都用来在执行代码上。除非抢占,否者它们通常会一直执行。

上下文切换

上下文切换,指的是从一个执行进程切换到另一个可执行进程。上下文切换时需要保存当前进程的运行状态,包括栈信息和寄存器信息,同时还要恢复上一个进程的运行时状态,包括恢复栈信息和寄存器信息,以及还有其它相关的状态信息。

上下文切换是耗性能的操作。

进程地址空间

用户空间中进程的内存,称为进程地址空间。进程地址空间,linux采用虚拟内存技术,系统为每个进程以虚拟方式共享内存空间。

进程只能访问系统分配的有效地址空间,地址空间也有相关的权限,比如读、写、执行。

linux使用内存描述符作为进程地址空间的存储结构,每个进程都关联一个内存描述符。

系统调用

linux将内存空间分为用户空间和内核空间,每个进程在用户空间进行分配,应用程序只能访问用户空间,不能访问内核空间。这样能够保证系统的安全性和稳定性。用户空间进程想要访问内核空间资源,必须通过系统调用才能访问。通过系统调用应用程序可以访问受限的资源和设备。

linux为系统调用提供了一层API封装,方便应用程序调用,这些API是使用C语言实现的。应用程序只要调用这些API就可以调用系统调用,访问受限资源。

系统调用是通过软中断实现的system_call(),linux为内置的所有系统调用都分配了一个唯一的系统调用号。应用程序执行系统调用时,系统通过系统调用号来找到对应的系统调用。系统调用后,用户空间的进程就会切换到内核,内核执行系统调用的时候就处于进程的上下文中。

中断

软中断

前面说的系统调用就是软中断的实现。

硬中断

硬中断指的是硬件设备发出的中断,比如键盘、网卡,当有数据输入时,会产生一个硬件中断信号到CPU,CPU通知中断处理程序处理硬中断。

内存管理

linux内核中的内存管理是以页为单位来管理的,尽管处理器最小的可寻址单位是字节。从虚拟内存角度来看,页就是最小的单位。

内存管理单元MMU,负责虚拟地址到硬件地址的转换。

页表

虚拟内存到物理内存的映射通过页表来实现,linux提供三级页表,虚拟内存通过页表完成到物理地址的转换。

SLAB

虚拟内存和物理内存的映射是以页为基本单位的,那如果内核需要小于一个页大小的内存,那就需要用到slab机制。

页缓存

页高速缓存(Page Cache)是Linux内核实现的磁盘缓存。主要用来减少对磁盘的I/O操作。将磁盘的数据缓存到cache中,把对磁盘的访问变为对内存的访问。

缓存的基本单位为页,所以也叫页缓存Page Cache。

应用程序的读read操作,内核会先从cache中读。判断是否缓存命中,如果在cache中直接返回。如果不在,先读磁盘,将磁盘数据先写入cache,再返回。

应用程序的写write操作,内核会将数据写入cache中,然后将cache中对应的page标记为dirty脏页,然后返回写入成功。

页回写

那cache中的页什么时候写入磁盘?

  1. 应用程序调用sync或fsync系统调用,内核立即写入磁盘;
  2. 内核定时线程flusher,会定期将cache写入磁盘。
    • 如果当前内存空间不足,flusher会将cache写入磁盘,清空cache释放内存;
    • 如果脏页在cache中驻留较长时间,flusher也会将其写入磁盘;

Linux.init

浅析Linux初始化init系统:

  1. sysvinit
  2. UpStart
  3. Systemd

参考资料

  1. 《Linux内核设计与实现》第三版
  2. 《深入理解Linux内核》
  3. 《Unix操作系统设计》

Post Directory