进程管理
进程的创建
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中的页什么时候写入磁盘?
- 应用程序调用sync或fsync系统调用,内核立即写入磁盘;
- 内核定时线程flusher,会定期将cache写入磁盘。
- 如果当前内存空间不足,flusher会将cache写入磁盘,清空cache释放内存;
- 如果脏页在cache中驻留较长时间,flusher也会将其写入磁盘;
Linux.init
浅析Linux初始化init系统:
- sysvinit
- UpStart
- Systemd
参考资料
- 《Linux内核设计与实现》第三版
- 《深入理解Linux内核》
- 《Unix操作系统设计》