进程管理 & (系统调用 内核同步)

wuyun--wy / 2023-08-12 / 原文

  • 进程管理
  • 在现代操作系统中,进程提供两种虚拟机制,虚拟处理器和虚拟内存
  • PCB描述一个正在执行的程序:打开的文件,挂起的信号,内核内部数据,处理器状态,一个或多个具有内存映射的内存地址空间及一个或多个执行线程。
  • 在2.6以前的版本中,PCB直接放在内核栈的尾端,或者放一个pcb_info间接索引,这样做是为了在x86那样寄存器较少的硬件体系结构只要通过栈指针就能计算它的位置,从而避免了额外的寄存器记录。当然在寄存器富余的机器上可以设置一个专门的寄存器。
  • Linux的进程之间存在一个明显的继承关系,所有的进程都是PID为1的init进程的后代,进程家族树,实际上我们可以通过这种继承体系,从一个进程出发遍历任何一个进程。当然我们也可以直接遍历任务队列,因为那是一个循环链表。
  • 进程创建
  1. fork() 和 exec() 函数,fork通过拷贝当前进程创建一个子进程,字进程和父进程的唯一区别在于PID不同,exec负责读取可执行文件并将其载入地址空间开始运行。
  2. 写时拷贝(copy-on-write),内核并不复制整个地址进程空间,而是让父进程和子进程共享同一拷贝,只有在需要写入的时候,数据才会被复制,从而使进程拥有各自的拷贝。资源的复制只有在需要写入的时候才进行,在此之前,只是以只读方式共享。fork的实际开销就是复制父进程的页表以及给字进程创建的唯一的进程描述符。在一般情况下,进程创建后都会马上运行一个可执行文件,这种优化可以避免拷贝大量根本不会使用的数据(地址空间常常包含数十兆数据),这很重要。 
  3. 除了不拷贝父进程的页表项,vfork 和 fork 的功能相同。
  4. Linux实现线程的机制非常独特,Linux把所有的线程当作进程来实现,线程仅仅被视为一个与其他进程共享某些资源的进程(如地址空间)。相当高雅的做法。
  5. 内核线程相比于普通进程没有独立的地址空间,他们只在内核空间中运行。
  6. 进程终止:设置task_struct 中的标志位,删除内核定时器,释放地址空间,离开信号等待队列,递减文件描述符,给子进程寻找养父,退出。在调用exit后,尽管进程已经不能运行了,但是系统还保留着它的task_struct,父进程会回收。
  • 内核的一些数据结构如链表,队列,映射,红黑树等。

 

  •                                                                        系统调用
  • 系统调用在用户空间进程和硬件设备之间添加了一个中间层。系统调用保证了系统的稳定和安全。
  • 系统调用陷入内核,陷入内核时的参数可以由寄存器传递,返回值也通过寄存器带入用户空间。

 

 

  • 内核同步
  • 原子操作
  • 死锁
  • 自旋锁
  • 读写自旋锁
  • 信号量
  • 互斥体
  • 顺序和屏障,编译器屏障防止指令重排,处理屏障,确保顺序。