Linux进程管理

进程=内核数据结构(PCB)+该程序的代码+数据集合

PCB

进程控制块,Process Ctrl Block,是操作系统为了管理进程设置的一个专门的结构体task_struct,操作系统用它来记录进程的外部特征,描述进程的运动变化过程,控制和管理进程

task_struct

pid:每个进程唯一标识符。pid为0的进程为调度进程,该进程是内核的一部分;pid为1的进程为init进程,它是一个普通的用户进程,但是以超级用户特权运行;pid为2的进程是页守护进程,负责支持虚拟存储系统的分页操作

#include<unistd.h>
pid_t getpid(void);     // 获取该进程的pid
pid_t getppid(void);    // 获取该进程的父进程pid
uid_t getuid(void);     // 获取调用该进程的实际用户id
uid_t geteuid(void);    // 获取调用该进程的有效用户id
gid_t getgid(void);     // 获取调用该进程的实际组id
git_t getegid(void);    // 获取调用该进程的有效组id

每个进程都有两个栈:用户空间栈和内核栈(系统空间栈),task_struct和系统空间栈存放位置如下(两个连续的物理页):

img

进程创建

Linux系统创建进程都是由已存在的进程创建的(除了0号进程),被创建的进程叫做子进程,创建子进程的进程就做父进程

img

0/1/2号进程

  • 0号进程:在内核初始化的过程中,会先通过struct task_struct init_task=INIT_TASK(init_task)创建0号进程,这是唯一一个不通过fork或者kernel_thread产生的进程,是进程列表的第一个
  • 1号进程:通过调用指令kernel_thread(kernel_init,NULL,CLONE_FS)从内核态切换到用户态来创建的,1号进程是所有用户态的祖先
  • 2号进程:通过调用指令kernel_thread(kthreadd,NULL,CLONE_FS|CLONE_FILES)来创建,2号进程负责所有内核态的进程的调度和管理,是内核态所有进程的祖先(注意,内核态不分线程和进程,都是任务)

为什么先创建0号进程,而不直接创建1号进程

简单来说就是Linux 的第一个进程不适合是一个真进程,需要一个没有数据之类东西的假进程

为什么要区分用户态和内核态

因为有了多个进程,对于关键资源来说,就会产生争用以及误操作破坏资源等情况。这时就需要对资源的访问权限进行一定的限制。x86提供了分层的权限机制,内核态具有最高的访问权限,而用户态访问核心资源时必须要切换到内核态才可以访问

fork

fork是类Unix操作系统上创建进程的主要方法,fork用于创建子进程,采用COW技术避免创建进程时大量拷贝,父子进程的执行次序不确定

vfork

起源:因为以前的fork当它创建一个子进程时,将会创建一个新的地址空间,并且拷贝父进程的资源,而往往在子进程中会执行exec调用,这样,前面的拷贝工作就是白费力气了,这种情况下,聪明的人就想出了vfork,它产生的子进程刚开始暂时与父进程共享地址空间(其实就是线程的概念了),因为这时候子进程在父进程的地址空间中运行,所以子进程不能进行写操作。并且当子进程占用着父进程的空间时,父进程不许执行,一旦子进程执行完exec或者exit后,子进程有了自己的空间,父进程才可能被调度运行

exec函数族

在Linux中使用exec函数族,系统调用execve()对当前进程进行替换,替换成一个指定程序,其参数包括文件名,参数列表以及环境变量

一旦一个进程调用exec类函数,它本身就死亡了,系统把代码段替换成新的程序的代码,废弃原有的数据段和堆栈段,并为新程序分配新的数据段和堆栈段,唯一留下的就是进程号

在这里插入图片描述

Copy-on-Write,COW

fork创建出的子进程,与父进程共享内存空间。 如果子进程不对内存空间进行写入操作的话,内存空间中的数据并不会复制给子进程,这样创建子进程的速度就很快 ,因为不用复制,直接引用父进程的物理空间 ,并且如果在fork函数返回之后,子进程第一时间exec一个新的可执行映像,那么也不会浪费时间和内存空间了

fork之后,kernel把父进程中所有的内存页的权限都设为read-only,然后子进程的地址空间指向父进程。当父子进程都只读内存时,相安无事。当其中某个进程写内存时,CPU硬件检测到内存页是read-only的,于是触发页异常中断(page-fault),陷入kernel的一个中断例程。中断例程中,kernel就会把触发的异常的页复制一份,于是父子进程各自持有独立的一份