目录
一. 冯诺依曼体系结构
二. 操作系统(OS(操作系统的英文缩写Operator System))
2.1概念
2-2 设计OS的目的
2.3 核心功能
2.4 如何管理(先描述再组织)
2.5 系统调用和库函数概念
三.进程
3.1 基本概念与基本操作
3.2 描述进程-PCB
3.3 如何查看进程
3.4 PID,PPID 和 STAT(进程状态status)
3.5 Z(zombie)-僵尸进程
僵尸进程危害
3.6 孤儿进程
四.进程优先级
4.1 PRI and Nl
4.1.2 更改NI值
五.调度队列
5.1 活动队列
5.2 过期队列
5.3 active指针和expired指针
六.环境变量
6.1环境变量相关的命令
6.2 常见环境变量
6.3 查看环境变量方法
6.4 通过代码如何获取环境变量
七. 进程地址空间
7.1虚拟地址
7.2mm_struct
7.3 为什么要有虚拟地址空间
一. 冯诺依曼体系结构
笔记本,服务器,PC等大部分计算机都遵守冯诺依曼体系。
网图:
解释图片:
输入单元:包括键盘,鼠标,扫描仪,写板等
中央处理器(CPU):含有运算器和控制器等
输出单元:显示器,打印机等这里的存储设备指的是内存,我们计算机存放游戏的磁盘叫外存!!
不考虑缓存情况,这里的CPU能且只能对内存进行读写!,不能访问外设(输入或输出设备)
二. 操作系统(OS(操作系统的英文缩写Operator System))
2.1概念
任何计算机系统都包含一个基本的程序集合,称为操作系统(OS)。
操作系统包括:
内核(进程管理,内存管理,文件管理,驱动管理)
其他程序(例如函数库,shell程序等等)
2-2 设计OS的目的
对下,与硬件交互,管理所有的软硬件资源
对上,为用户程序(应用程序)提供一个良好的执行环境
2.3 核心功能
在整个计算机软硬件架构中,操作系统的定位是:一款纯正的“搞管理”的软件
2.4 如何管理(先描述再组织)
1.描述,用struct结构体
2.组织,用链表或其他高效的数据结构
2.5 系统调用和库函数概念
系统调用在使用上,功能比较基础,比如(open,read,_exit()...)就是系统调用。
用户的要求相对也比较高,所以,有心的开发者可以对部分系统调用进行适度封装,从而形成库。
比如(fopen,fread,fget,exit()...)
三.进程
3.1 基本概念与基本操作
课本概念:程序的一个执行实例,正在执行的程序等
内核观点:担当分配系统资源(CPU时间,内存)的实体。
3.2 描述进程-PCB
基本概念
进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
课本上称之为PCB(process control block),Linux操作系统下的PCB是: task_struct。
3.3 如何查看进程
比如我们有一个程序,让他一直运行
我们可以输入: gcc -o mytest test.c
生成:
在其运行期间:
就会有:
这些是什么?下面3.4会讲到
3.4 PID,PPID 和 STAT(进程状态status)
进程id (PID)
父进程id(PPID)
进程状态(STAT)
R运行状态(running):并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
S睡眠状态(sleeping):意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠
(interruptible sleep))。
D磁盘休眠状态(Disksleep)有时候也叫不可中断睡眠状态(uninterruptiblesleep),在这个
状态的进程通常会等待IO的结束。
T停止状态(stopped):可以通过发送SIGSTOP信号给进程来停止(T)进程。这个被暂停的
进程可以通过发送SIGCONT信号让进程继续运行。
X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。
3.5 Z(zombie)-僵尸进程
僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()函数)没有读取到子进程退出的返回代码 时就会产生僵死(尸)进程
僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
所以,只要子进程退出,父进程还在运行,但 父进程没有读取子进程状态,子进程进入Z状态。
僵尸进程危害
维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护!!!
那一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费!!因为数据结构对象本身就要占用内存。
3.6 孤儿进程
父进程先退出(跟僵尸区别一下),子进程还在,就称之为“孤儿进程”。
孤儿进程被1号init进程领养,被init进程回收。
四.进程优先级
cpu资源分配的先后顺序,就是指进程的优先权(priority)。
把重要的进程运行到指定的CPU上,或者把不重要的进程安排到某个CPU,可以大大改善系统整体性能。
UID:代表执行者的身份(就像原神的UID一样)
PRI:代表这个进程可被执行的优先级,其值越小越早被执行
NI:代表这个进程的nice值
4.1 PRI and Nl
PRI值越小越快被执行,那么加入nice值后,将会使得新的PRI变为:PRI = PRI(默认值) + nice
当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高(越快被执行)。所以,调整进程优先级,在Linux下,就是调整进程nice值。
nice其取值范围是-20至19,一共40个级别。
4.1.2 更改NI值
用top命令更改已存在进程的nice:
先输入top ->进入top后按“r”->输入进程PID->输入nice值
五.调度队列
一个CPU拥有一个 runqueue
如果有多个CPU就要考虑进程个数的负载均衡问题
调度队列中存在 活动队列 和 过期队列。
5.1 活动队列
时间片还没有结束的所有进程都按照优先级放在活动队列
注:时间片:当代计算机都是分时操作系统,没有进程都有它合适的时间片(其实就是一个计数器)。时间片到达,进程就被操作系统从CPU中剥离下来。
nr_active: 总共有多少个运行状态的进程
queue[140]: 一个元素就是一个进程队列,相同优先级的进程按照FIFO规则进行排队调度,所以,数组下标就是优先级!
当一个进程运行完时,就会进入 过期队列 等待第二次运行
5.2 过期队列
过期队列和活动队列结构一模一样
过期队列上放置的进程,都是时间片耗尽的进程
当活动队列上的进程都被处理完毕之后,对过期队列的进程进行时间片重新计算
5.3 active指针和expired指针
active指针永远指向活动队列
expired指针永远指向过期队列
因此,在合适的时候,只要能够交换active指针和expired指针的内容,就相当于有具有了一批
新的活动进程!就可以继续运行被 过期队列重置的进程。
六.环境变量
环境变量(environmlentvariables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。
如:我们在编写C/C++代码的时候,X在链接的时候,从来不知道我们的所链接的动态静态库在哪
里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。
6.1环境变量相关的命令
1. echo:显示某个环境变量值
2. export:设置一个新的环境变量
3. env:显示所有环境变量
4. unset:清除环境变量
5. set:显示本地定义的shell变量和环境变量
6.2 常见环境变量
1. PATH:指定命令的搜索路径
2. HOME:指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
3. SHELL: 当前Shell,它的值通常是/bin/bash。
6.3 查看环境变量方法
echo $NAME(NAME:你的环境变量名称)
例子: PATH
6.4 通过代码如何获取环境变量
1. 通过第三方变量environ获取
比如:
注意: libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时要用 extern 声明。
2. getenv()
3 .putenv()
4.putenv()和 getenv()的区别
七. 进程地址空间
7.1虚拟地址
我们输入一段代码(不想敲了)
1.首先我们使用fork建立 一个父进程和 一个子进程。
2.然后printf出他们的地址,我们就会发现父子进程,输出地址是一致的!!!
因为地址值是一样的,说明,该地址绝对不是物理地址!
在Linux下,这种地址叫做虚拟地址
我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS(操作系统)统一管理。OS必须负责将 虚拟地址 通过页表映射关系转化成 物理地址 。
网图:
7.2mm_struct
linux 下进程的地址空间的 所有的信息的结构体是mm_struct(内存描述符). 每个进程只有一个mm_struct结构,在每个进程的 task_struct 结构中,有一个指向该进程的结构。
通过它,我们就可以访问我们需要的 代码段 或者 数据段,
如图所示:
7.3 为什么要有虚拟地址空间
如果直接使用物理内存的话,一个进程就是作为一个整体(内存块)操作的,如果出现物理
内存不够用的时候,我们一般的办法是将不常用的进程拷贝到磁盘的交换分区中,好腾出内
存,但是如果是物理地址的话,就需要将整个进程一起拷走,这样,在内存和磁盘之间拷贝
时间太长,效率较低。
如果有虚拟地址
因为有地址空间的存在,所以我们在C、C++语言上new,malloc空间的时候,其实是在地址
空间上申请的,物理内存可以甚至一个字节都不给你。而当你真正进行对物理地址空间访问
的时候,才执行内存的相关管理算法,帮你申请内存,构建页表映射关系(延迟分配),这
是由操作系统自动完成。
因此虚拟地址可以帮助我们提高效率,和减少空间的浪费,更高效运行进程。