目录
1. 冯诺依曼体系结构
冯诺依曼体系结构:现代计算机的硬件体系结构。
五大硬件单元以及典型设备:
-
输入设备:采集获取数据 键盘
-
输出设备:数据输出 显示器
-
存储器:内存 (数据缓存). 硬盘和内存的存储介质是不一样的;内存的存储介质是一种易失性介质:数据断电后丢失。所有设备都是围绕内存工作,内存是中间的数据缓冲带---这种硬件体系结构所带来的软件行为
-
运算器:中央处理器CPU
-
控制器:4+5=中央处理器CPU
硬件结构决定了软件行为:QQ聊天。所有的硬件都是围绕内存工作的。
2. 操作系统:系统内核+外部应用
内核:管理计算机上的软硬件资源
应用:为了使计算机更加好用
-
操作系统功能: 管理(先描述再组织)计算机上的软硬件资源。 目的:让计算机更加好用。
-
操作系统如何管理计算机上的软硬件资源:先将被管理者描述出来,将这些描述信息组织起来,通过这个描述信息实现对被管理者的管理。( 先描述,再组织来进行管理)
-
系统调用接口:操作系统向上提供的系统核心功能的接口
- 库函数和系统调用接口的关系:库函数封装了系统调用接口
- 程序:一系列有序的指令集合--就是程序员编写的代码--存储在硬盘中
- 冯诺依曼--所有的数据指令想要被cpu进行处理,第一步就是将代码和数据加载到内存中
操作系统如何实现多个程序的调度运行:将这个运行中的程序描述起来,然后将这些描述组织起来进行管理
通过实现对PCB的调度管理实现对运行中程序的调度运行--对于操作系统来说这个描述信息-pcb就是进程
-
cpu分时机制:cpu以极快的速度切换调度运行所有的程序,造成大家都在同时运行的假象
3. 进程
-
进程就是PCB(进程控制块),是操作系统对一个运行中程序的描述,通过这个描述,实现对程序的运行调度。这个pcb/描述在linux中是一个结构体--struct task_struct{...}
描述信息:
-
内存指针能够找到内存中运行的程序代码以及数据
-
上下文数据可以保存程序调度切换时正在处理的数据
-
程序计数器保存进程切换时程序即将执行的下一步指令,等等....通过描述这些信息实现控制一个程序的运行。
操作系统认为现在要运行哪个程序,则找到对应的pcb,将pcb中保存的各种描述信息加载到cpu寄存器上
cpu的分时机制:进程在操作系统中是调度切换运行的,每个进程都有一个CPU时间片(一个进程在CPU上的运行时间段),在CPU上时间片运行完毕后则切换到下一个进程
操作系统该调度哪个进程在cpu上运行,操作系统中有一系列的调度算法
cpu多核--多个处理核心--每个核心都有自己的寄存器,可以调度一个程序的运行
-
并发:轮询处理执行
-
并行:同时运行/执行
-
创建进程:进程就是pcb,意味着创建一个进程,就是创建一个pcb
-
pid_t fork(void)--通过复制调用进程(父进程)创建一个新的进程(子进程)
创建了一个新的pcb,然后从父进程pcb中复制了很多数据过来
复制的信息:内存指针,程序计数器,上下文数据......
-
内存指针:子进程与父进程运行的代码其实是一样的---指向同一块物理内存中的数据以及指令
-
程序计数器/上下文数据:子进程被创建出来后,运行位置与父进程是完全一样的,下一步即将执行的指令都是从创建子进程成功之后开始的
创建一个子进程出来,跟父进程干的事情是一样的,因为它们的运行的代码以及当前的运行位置都是一样的。
-
这个函数的返回值对于父子进程是不一样的:在父进程中返回创建的子进程的pid,在子进程中返回0。
-
通常根据fork的返回值进行代码的分流,让父子进程进入不同的判断执行体完成不同的功能
-
父子进程代码共享,数据独有
-
fork的基本使用与返回值认识
理解为什么父子进程运行的代码和位置都一样?
理解如何通过返回值进行代码分流?
-
pit_t gitpid(void)--返回调用进程的pid--谁调用就返回谁的pid
4. 进程状态
进程的查看:ps -ef / ps-aux
-
进程状态: 就绪/运行/阻塞
Linux下进程状态:
-
运行态 R:就绪/运行 (正在运行的以及只要拿到时间片就能运行的). ----运行状态的进程才会被操作系统调度在cpu上运行
-
可中断休眠态 S:当前的阻塞能够被中断唤醒
-
不可中断休眠态 D:当前的阻塞不会被中断唤醒,等待条件满足自己醒来
-
停止态 T :停止运行,什么都不干
-
僵死态 Z: 进程已经退出了,但是资源没有完全释放的一种状态 ---这是一种等待后续处理的状态
-
命令:ps -aux / kill / kill -9 强制杀死进程
-
僵尸进程:处于僵死态的进程--进程已经退出,但是资源没有完全释放。
-
僵尸进程的产生原因: 子进程先于父进程退出,但是父进程没有关注子进程的退出状态,因此子进程成为僵尸进程。
子进程先于父进程退出,退出后,为了保存自身的退出原因(返回值),因此资源没有完全释放,但是若父进程没有关注这个退出状态,则子进程虽然退出了,但是资源没有完全释放,处于僵死状态,成为僵尸进程。
-
资源没有完全释放的原因,子进程要保存退出原因
-
僵尸进程的危害:资源泄露(进程数量资源,结构体资源) 一个用户所能创建的进程数量(ulimit -a 命令)有限,并且资源没有完全回收会占据内存资源
处理方法:退出父进程(父进程退出,子进程保存退出原因就没有意义了因此也就被释放了)
-
僵尸进程的避免:进程等待(父进程等待子进程退出,获取退出返回值,释放子进程资源)
为什么要创建一个子进程--子进程干的事情跟父进程是一样的 ---创建子进程可以分摊父进程的工作提高效率
-
孤儿进程:父进程先于子进程退出,子进程则成为孤儿进程,孤儿进程运行在系统后台,父进程成为1号进程 init。
孤儿进程是不会成为僵尸进程的,因为1号进程随时关注子进程退出。
-
守护进程(精灵进程尾):是一种特殊的孤儿进程,父进程是1号进程,运行在后台+与终端以及登陆会话脱离关系,不再受影响。
守护进程通常是一种运行在系统后台的批处理(默默的做一些循环反复的事情)程序
守护进程/精灵进程(进程以d结尾):特殊的孤儿进程,脱离终端,会话影响。运行在后台----调研实现
进程状态:Linux下的进程状态/僵尸进程的产生原因,危害,处理和避免/孤儿进程产生以及特性/守护进程
-
进程优先级:一个进程对于cpu资源获取的优先权----权级其实就是一个数字
交互式进程:直接与用户进行交互的进程--要求最好能够更加优先的被cpu处理
批处理进程:在后台默默做循环工作的进程
优先级的作用:让操作系统运行的更加合理
CPU密集型程序/io密集型程序
5. 环境变量
-
环境变量(env 命令查看):配置系统运行环境参数的变量
环境变量的好处:使系统运行环境配置更加简单灵活,可以通过设置环境变量给一个进程传递参数信息
-
环境变量的操作:
查看环境变量:env/set(查看所有变量,包含环境变量) / echo(直接打印某一个环境变量的值)
设置环境变量:export
删除环境变量:unset
$path, 把path当作变量
-
额外作用:向进程传递参数
操作命令:
env:查看所有环境变量,相当于是set子集
echo:打印指定环境变量的内容
set:查看shell中所有变量信息
export:设置一个环境变量,
unset:删除一个变量
MYVAL=1000
export MYVAL
./env | grep MYVAL
环境变量特性:具有继承特性的,子进程默认拥有父进程的环境变量---环境变量也可以用于参数的传递
典型:PATH-系统命令程序的默认搜索路径
-
代码中对环境变 量的操作:
1、main函数的第三个参数
int main(int argc,char* argv[],
char *env[])--env保存环境变量
2、通过一个全局变量 extern char** environ;--environ保存环境变量 (在本文件中声明有这个变量/然而这个变量的具体内容实际上是外部的,标准库)
3、char *getenv(const char * name)--通过环境变量名称获取一个指定环境变量的数据
-
变量的声明:告诉编辑器,有这个变量存在(但是这个变量不一定是我们自己定义的,这种声明使用的变量通常都是一个本文件之外的全局变量)
-
变量的定义:告诉编辑器,这个变量是什么样子的
6. 程序地址空间
程序地址空间:进程的虚拟地址空间
地址:对内存单元的编号
指针:指针就是一个存放地址的变量
程序是不占用内存的,运行起来的程序被加载到内存,才会占用内存
一个全局变量,在子进程中修改后打印100,父进程中依然打印1
数据不同,表示肯定没有使用同一块内存空间(一块内存空间不可能存储两个数据) 父子进程打印的数据不同但是地址却是相同的---矛盾
-
虚拟地址空间其实就是一个结构体mm_struct;--是一个对内存空间的描述--通过这个描述向进程虚拟出一个完整的,连续的内存空间
size---表示内存大小
code_start/code_end:描述代码段的起始与结束
-
虚拟地址空间:操作系统通过mm_struct结构体为一个进程描述的虚拟的,连续的,完整的地址空间
-
为什么要描述这么一个空间? 为了能够实现不让进程直接访问物理内存
进程直接访问物理内存:
内存地址:内存区域的编号
每个进程都有一个自己的进程地址空间
创建子进程--父子进程代码共享,数据独有
我们在进程中所访问到的地址实际是一个虚拟地址
程序地址空间-->进程地址空间-->虚拟地址空间
虚拟地址空间:通过一个结构体描述出一块完整的连续的线性的地址空间
size/code_start/code_end /data_start/data_end
mm_struct结构体---内存描述符
直接使用物理内存:内存利用率低,缺乏内存访问控制
-
虚拟地址与物理地址之间的映射:页表
页表主要功能:映射虚拟地址与物理内存的关系/提供内存访问控制
通过页表映射实现数据在物理内存上的离散式存储,提高了内存利用率
通过页表进行了内存访问控制
每个进程都有自己的虚拟地址空间,因此进程间保证了独立性。
操作系统通过虚拟地址空间向进程描述了一个完整的连续的虚拟地址空间,供进程使用,但是在物理内存中进程数据的存储采用离散式存储(提高内存利用率),并且使用页表映射虚拟地址与物理地址的映射关系,并且在页表中可以实现内存访问控制(标志位表示内存的访问权限)
-
如何通过虚拟地址得到物理地址:分段式内存管理/分页式内存管理/段页式内存管理
-
分段式 内存地址的组成:段号+段内偏移 段表(段号-物理段起始地址) 对程序内存管理比较友好 便于程序员/编译器的内存管理(优点)
-
分页式 虚拟地址的构成:页号+页内偏移 提高内存利用率(优点)
-
段页式(先分段,在每一段采用页表) 虚拟地址的构成 段号+段内页号起始+页内偏移+段表+段内页表(在每一个分段内又采用分页式管理) 集合了分页式与分段式的优点(优点)