目录
1 冯诺依曼体系
我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系
我们所认识的计算机,都是有一个个的硬件组件组成:
- 输入单元:包括键盘, 鼠标,扫描仪, 写板等
- 中央处理器(CPU):含有运算器和控制器等
- 输出单元:显示器,打印机等我们常见的计算机,如笔记本。我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系。
关于冯诺依曼:
这里的存储器指的是内存 不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备) 外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。 一句话,所有设备都只能直接和内存打交道
2 操作系统(Operator System)
操作系统:对下与硬件交互,管理所有的软硬件资源。对上为用户程序(应用程序)提供一个良好的执行环境。一句话就是操作系统是管理软硬件的软件。
3 如何理解管理
3.1计算机管理硬件
- 描述起来,用struct结构体
- 组织起来,用链表或其他高效的数据结构
总结就是六个字:先描述,再组织
3.2 管理逻辑图
3.3 怎样管理
操作系统是怎么管理进行进程管理的呢?很简单,先把进程描述起来,再把进程组织起来!
4 什么是进程?
当你写完一个程序的时候,在没运行的时候,代码存在于哪里呢?存在于磁盘中,当程序运行的时候,程序就会被加载到内存之中,此时该程序还不是进程。在一个操作系统中,除了运行你的程序之外,还运行着其他的程序,那么系统中这些程序都是杂乱无章的吗?当CPU处理这些任务的时候考不考虑优先级呢?
运行中程序的管理:先描述再组织
描述过程:操作系统为每一个运行的程序用一个 struct task_struct 结构体来描述运行的程序的属性和信息。
组织过程:可以认为把创建的strcut 用双向链表进行链接。
操作系统中为每一个运行的程序维护一个数据结构,数据结构中应该存放该进程的所有相关的属性和信息。
所以说,进程=磁盘中的代码+内核的数据结构
在Linux操作系统下,我们称它为PCB,Process Control Block,即进程控制模块。
5 查看进程
系统调用
想象一下,如果操作系统完全暴露在用户面前,对于新手用户可能会误触到操作系统内核的数据或者指令,导致出现不可挽回的后果。于是,操作系统为了安全考虑,不会将自己的底层直接交给用户操作,而是将操作系统封装起来,并提供一些特定的接口以供用户使用,这样的由操作系统给用户提供的操作接口,就被称为系统调用。
进程查看
上面我们已经了解到了进程,那么对于系统中的进程我们该怎么查看呢?下面介绍几种查看进程的系统调用指令。
5.1 ps ajx显示所有进程信息
但是,上述命令不利于我们查找自己的进程信息,如下我们编写一个程序名为process,运行之后想要在系统中查看它的进程信息,我们可以使用:
ps ajx | head -1&&ps ajx | grep process来查看它。(head表示显示头栏)
创建的process程序,内容随意。
接下来我们通过 ps ajx | head -1&&ps ajx | grep process 命令查看进程信息
查看进程的时候发现出现了两个进程,其中一条是执行grep命令的进程。要想过滤掉它,我们可以用ps ajx | head -1 && ps ajx | grep Process | grep -v grep。
5.2 /proc(内存文件系统)
进程的信息还可以通过 /proc 系统文件夹查看,如果我们要想查看PID(Process I D)为 2的进程,可以进行如下操作。
5.2.1 ls /proc/PID
那么这个数字2 是什么呢,在上述我们使用 ps ajx 命令时,会发现头栏有PID(Process I D) 。即为标识一个进程的重要信息,类似于身份证号的概念,对于系统中的每一个进程,系统都会分配给其一个唯一的PID,/proc就是以这个来查看进程信息的。
例如如下进程的PID 为2121
接下来我们使用/proc/PID 命令进行查看
5.2.2 ls /proc/PID -al
该指令用来查看进程的更多信息,圈出来的红框里的两个信息
cwd:表示当前进程运行的路径
exe:表示可执行文件的路径
5.3 PPID与PID
PID即Process ID,上面讲到了PID是一个进程的标识符,担当着“身份证号”的角色,每一个系统中的进程都有唯一的PID。那么PPID是什么呢?即Parent Process ID,为当前进程的父进程ID。
为什么要有父进程的这个概念:当我们在执行shell脚本的时候,这个动作是由登录的shell(父进程)处理的,有的也叫bash(shell 或者bash 就是命令解释器), 为了执行指令,父进程bash会创建一个新的子进程用来代替父进程执行命令,子进程是父进程的一个副本,它独立运行,这种方式保证了脚本执行的安全性和隔离性,避免了对父进程状态的影响。后面我们会看到bash.
6 getpid(),getppid()
除了上述的查看一个进程的PID与PPID的方法,系统还提供了一个调用接口
通过系统调用获取进程标示符
getppid()是获取父进程的PID
当我们结束这个程序再次运行的时候,我们发现,每次重新形成一个进程时,系统都会为它分配一个ID,所以第一次的ID是22783,第二次的变成了23883,但是后面的父进程14105为什么不变呢?
7 父进程与子进程
通过上图我们可以看到父进程的PID 14105是不变的,那么后面的~bash是什么呢,前面也有所说,bash是命令解释器, 为了执行指令,父进程bash会创建一个新的子进程用来代替父进程执行命令,子进程是父进程的一个副本,它独立运行,这种方式保证了脚本执行的安全性和隔离性,避免了对父进程状态的影响
7.1子进程的创建 (fork)
在上面我们已经了解到了进程的形成过程,以及怎么查看进程相关的信息和属性,,且我们知道了父进程和子进程,那么我们该如何自己创建一个子进程呢?操作系统已经为用户提供了一个系统调用接口来创建子进程:fork()
✪认识fork
✍fork()返回值
fork()创建一个子进程的时候会把该进程的PID传给父进程,而把0传给该子进程,若创建子进程失败会把-1传给父进程,接下来我们用一个例子来进行说明。
运行结果:
我是父进程:pid:3058,ppid :14105,id 3059
我是子进程:pid :3059,ppid :3058,id 0
解释一下:前面也说过fork()是一个创建子进程的函数,当我们创建一个子进程的时候。
我是子进程:pid :3059,ppid :3058,id 0,子进程的pid会传给父进程:我是父进程:pid:3058,ppid :14105,id 3059。所以父进程的id 为3059,且子进程的ppid为3058,而父进程pid为3058,说明其为父子进程关系。而ppid 14105的这个进程不是别的,是bash.
总结
- fork()之后,会有父进程+子进程两个进程在执行后续代码。
- fork()后续的代码,被父子进程共享。
- 通过返回值不同,让父子进程执行后续共享代码的一部分。