文章目录
- 什么是进程
- 如何管理进程
- 查看进程
- 创建子进程
什么是进程
我们用一张Windows下的任务管理器图来辅助我们观看,我们一个可以看到应用在运行的时候就是一个个进程。
所以我们启动了一个软件本质上就是启动了一个进程。
在Linux下运行一条命令,./XXX运行的时候其实就是在系统层面创建了一个进程!!!
我们知道代码会生成可执行程序,而可执行程序是不能被OS(操作系统调度的),只有在可执行程序被运行变成进程的时候才会被调度,因为OS(操作系统)只能对进程进行调度
如何管理进程
我们知道Windows下存在大量的exe文件,类比到Linux所以Linux下肯定存在大量的exe文件。所以我们可以理解Linux是可以同时加载多个程序的,Linux是同时存在大量的进程在系统的内存中的。
单个可执行程序被加载到内存,并且被CPU调度过程:
多个可执行程序被加载到内存变成进程:
那么Linux系统要不要管理这些进程呢?
答案:肯定是要的。
当多个可执行程序被加载到内存变成进程,CPU该如何调度呢?所以Linux操作系统必须对这些进程进行管理。
那么Linux系统是如何管理大量进程的呢?
答案:先描述,再组织
我们先定义一个对象来描述单个进程的核心信息比如进程被调度的时间、进程的优先级、进程的上下文数据等等。然后再用数据结构对这些进程进行管理。
而描述进程的对象叫做进程PCB结构体。PCB包含了所有进程属性。
如何理解对象或者类呢?
人们认识世界是通过“属性”来认识世界的。
比如:有一种动物它是人类的朋友,高兴的时候会摇尾巴,遇到陌生人会汪汪叫。我们立马会想到这是狗。
再比如:有一种动物体型很大,额头上会写一个王字,是食肉动物。我们会立马想到这是老虎。
那么属性是数据吗?
答案:是的,属性也是数据。
属性和程序内的代码和数据有关系吗?
答案:没有关系,它们是两套概念没有任何联系。
那么Linux是用什么数据结构管理这些进程PCB的呢?
我们可以看到Linux用链表的结构来管理这些进程PCB。
这样我们对进程的管理,变成了对进程PCB结构体链表的增删查改。
从这里我们可以知道 进程 = 对应代码和数据 + 进程对应的PCB结构体
PCB是什么?
例子:假如要表明你是清华的学生,是你人在清华就表明你就是清华的学生吗?这样清华的保安,社管阿姨,食堂阿姨等等这些人也是清华的学生。
可想而知要表明自己试清华的学生不仅仅是如此,还必须各种信息被录入到清华的教务管理系统中。
那么清华校长如果要开除某个学生仅仅是让学生离开清华而已吗?
不仅仅是如此,还必须在教务系统中删除这个学生的信息。
上面的清华的这一套管理体系就是PCB的管理体系。
那么进程PCB具体保存哪些数据呢?
如图所示:
查看进程
前面我们说了这么多那么我们该如何在Linux操作系统中查看进程呢?
首先我们写一个死循环程序,这样进程就可以一直存在便于我们查看。
生成可执行程序,然后运行可执行程序变成进程。
创建一个新的会话然后在新的会话中查看进程。
我们看到用查看进程的命令确实看到了进程,如果我们把进程Ctrl c掉还会存在进程吗?
我们可以看到进程确实消失了。而图里的进程我们可以理解为,grep也是一个进程所以当我们查看的时候,grep进程也会存在。
我们还有一种查看进程的方法。
Linux下有一个专门保存进程的proc文件。
我们可以看到确实查到了该进程。
我们查看该进程文件内部。
我们会看到关于进程的各种信息。
其中的cwd而cwd就是当前进程工作目录。也就是可执行程序当前存在的位置。
每一个进程都会保存自己的工作路径。
proc下的目录时动态的,当进程被删除时Linux会自动删除保存进程的目录。
我们如何用代码获取进程的pid呢?
Linux操作系统给我们提供了一个接口,getpid()可以帮助我们获取当前进程pid。
其中pid_t是一个整形。
我们可以看到确实获得了进程的pid,那么该pid是这个进程的吗?我们用kill发送9号信号来杀掉进程,看进程会被会被kill。
我们可以看到,用该进程pid发送kill信号确实把该进程杀掉了。
我们之前查看进程的时候应该看到了ppid那么ppid是什么呢?
ppid是该进程的父进程ID,那么我们如何获取呢?
Linux也给我们提供了getppid()接口,可以获得父进程ID。
那么看到了父进程那么该父进程是谁呢?
我们可以看到父进程就是bash我们之前在shell的运行原理中也学过bash这里就不过多介绍。
这里的bash也是可以被kill掉的,这里就不过多演示,大家有兴趣可以自己试验。
创建子进程
我们学习了进程,也学了父进程那么我们该如何自己创建一个进程呢?
Linux也给我们提供了接口fork()。
我们可以从英文中知道返回值:
具体如何使用fork,下次博客在介绍。