一、冯·诺依曼体系结构
数学家冯·诺依曼提出了计算机制造的三个基本原则,即采用二进制逻辑、程序存储执行以及计算机由五个部分组成(运算器、控制器、存储器、输入设备、输出设备),这套理论被称为冯·诺依曼体系结构。
冯·诺依曼最先提出程序存储的思想,并成功将其运用在计算机的设计之中。冯·诺伊曼体系结构是现代计算机的基础,现在大多计算机仍是冯·诺伊曼计算机的组织结构,因此冯·诺依曼又被称为“现代计算机之父”。 存储器:用来存放数据和程序 运算器:主要运行算数运算和逻辑运算,并将中间结果暂存到运算器中 控制器:主要用来控制和指挥程序和数据的输入运行,以及处理运算结果 输入设备:用来将人们熟悉的信息形式转换为机器能够识别的信息形式,常见的有键盘,鼠标等 输出设备:可以将机器运算结果转换为人们熟悉的信息形式,如打印机输出,显示器输出等
我们这里说的内存,主要是指主存。就是主板上插的内存条。它的读写速度比磁盘快了几十万倍。但是相对于CPU的速度依旧还是慢。那么主存和CPU之间,可以继续添加速度更快的过度层。所以intel i7的存储器层次结构是这样的。
关于冯诺依曼
- 这里的存储器指的是内存
- 不考虑缓存情况,这里的CPU能且只能对内存进行读写,不能访问外设(输入或输出设备)
- 外设(输入或输出设备)要输入或者输出数据,也只能写入内存或者从内存中读取。
- 一句话,所有设备都只能直接和内存打交道。
二、操作系统(operating system)
OS是什么? 一款软件,专门针对软硬件资源进行管理工作的软件。 官方概念
- 任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。笼统的理解,操作系统包括:
内核(进程管理,内存管理,文件管理,驱动管理) 其他程序(例如函数库,shell程序等等)
管理不是直接管理,是对对象的数据处理。 操作系统是用C语言写的,所以一般描述一个对象的集合我们可以使用结构体。 操作系统的理念:对目标的管理,转换成对数据的管理!
2.1 系统调用和库函数概念
在开发角度,操作系统对外会表现为一个整体,但是会暴露自己的部分接口,供上层开发使用,这部分由操作系统提供的接口,叫做系统调用。
系统调用在使用上,功能比较基础,对用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库,有了库,就很有利于更上层用户或者开发者进行二次开发。
三、进程
基本概念
表层概念:程序的一个执行实例,正在执行的程序等 内核观点:担当分配系统资源(CPU时间,内存)的实体
3.1 描述进程-PCB
进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。课本上称之为PCB(process control block),Linux操作系统下的PCB是: task_struct
task_struct-PCB的一种 在Linux中描述进程的结构体叫做task_struct。 task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。
操作系统并不是直接管理进程,而是通过管理PCB来管理进程,所以进程就得到了一个真正的描述:进程 = 程序文件内容(代码和文件相关内部数据)+ 相关的数据结构(task_struct,由OS自动创建)
3.2 查看进程
3.2.1 通过系统目录查看
在系统根目录下有一个proc文件,里面存放了进程的名字 这些数字就是进程的标识符(PID),如果知道进程的pid就可以通过这个查找该进程。 例如ls /proc/1
3.2.1.1 通过系统调用获取进程标示符
- 进程id(PID),对应函数 getpid()
- 父进程id(PPID),对应函数 getppid()
3.2.2 通过命令ps查看
单独使用ps命令,会显示所有进程信息。 命令:ps aux 命令:ps axj 作用类似
还可以通过grep查找想要的进程
3.3 task_ struct内容分类
- 标示符(PID): 描述本进程的唯一标示符,用来区别其他进程。
- 状态: 任务状态,退出代码,退出信号等。
- 优先级: 相对于其他进程的优先级。
- 程序计数器: 程序中即将被执行的下一条指令的地址。
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
- 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
- 其他信息
3.3.1 上下文数据
进程执行时处理器的寄存器中的数据。
我们知道CPU的运行速度是相当快的,但每个进程也不可能很快停止,比如我们打开的应用程序QQ、微信可能一天都在运行,但是大多数计算机CPU只有一个,不可能一直运行这一个进程。
所以CPU规定每个进程单次运行的时间片(一个进程单次运行的最长时间),比如:10ms 这样在单CPU下,让用户感到多个进程同时在运行,本质是通过CPU的快熟切换完成的。
那么在切换的时候,下一次再运行不可能再从零开始,所以就需要记录上次运行结束的信息,CPU只有一套寄存器用于存放当前进程的运行数据,当进程单次运行结束时,需要保存当次运行的相关数据(来自寄存器),再次运行进程的时候,恢复上次运行的信息即可。
3.4 创建子进程
常用函数fork()创建子进程
关于fork的返回值:
失败:返回值<0 成功:
- 给父进程返回子进程PID
- 给子进程返回0
那么fork()创建进程有什么特点吗? 子进程:
PCB(task_struct): 以父进程为模板初始化 代码和数据:继承父进程的代码和数据(父子共享,但如果发生修改就会发生“写时拷贝”)
使用fork函数创建子进程后就有了两个进程,这两个进程被操作系统调度的顺序是不确定的,这取决于操作系统调度算法的具体实现。
3.5 进程状态
为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。 下面的状态在kernel源代码里定义:
static const char * const task_state_array[] = {
"R (running)",
"S (sleeping)",
"D (disk sleep)",
"T (stopped)",
"t (tracing stop)",
"X (dead)",
"Z (zombie)",
};
R-运行状态
并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列 里。每一时刻只有一个进程在使用CPU。
S、D-休眠状态
S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠(interruptible sleep))。 D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束。
进程完成某种任务时,任务条件不具备,需要进程进行某种等待。
常见概念:
挂起等待(阻塞):PCB从运行状态运行队列放到等待队列 唤醒进程:PCB从等待队列到运行队列
T-暂停状态
可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可 以通过发送 SIGCONT 信号让进程继续运行。
t - 追踪状态
例如程序的调试
X - 死亡状态
这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
Z - 僵尸状态
僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵死(尸)进程僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态
僵尸进程危害 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态。 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护。
那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费。因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间! 会造成内存泄漏
3.6 孤儿进程
父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢? 父进程先退出,子进程就称之为“孤儿进程”孤儿进程被1号init进程(OS)领养,当然要有init进程回收喽。
3.7 进程优先级
基本概念
- cpu资源分配的先后顺序,就是指进程的优先权(priority)。
- 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
- 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。
查看系统进程 在linux或者unix系统中,用ps –l命令
我们很容易注意到其中的几个重要信息,有下: UID : 代表执行者的身份 PID : 代表这个进程的代号 PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号 PRI :代表这个进程可被执行的优先级,其值越小越早被执行 NI :代表这个进程的nice值,也叫优先级
PRI and NI
- PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高
- 那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值
PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为PRI(new)=PRI(old)+nice - 这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行所以,调整进程优先级,在Linux下,就是调整进程nice值
- nice其取值范围是-20至19,一共40个级别。
用top命令更改已存在进程的nice top 进入top后按“r”–>输入进程PID–>输入nice值 此时的PRI = 原来的80+NI值8 = 88
NI的值只能在-20~19之间,而且每次修改是在最原始的基础修改的。
建议不要修改进程的优先级
3.8 其他概念
- 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
- 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
- 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
- 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发
|