目录
1、冯诺依曼体系结构
1、上图很好的展示出了数据在冯诺依曼体系结构中是如何传输的:
由输入单元存储器
cpu
存储器
输出设备
2、为何不直接由输入单元到CPU再到输出设备呢?
由下图可知磁盘到寄存器(CPU的组件)读取数据越快,价格越是昂贵,所以目前不可能让寄存器像磁盘那么大。尽管寄存器处理数据很快,但磁盘数据太多如果直接传输会导致效率急剧降低(这是由于速率是由最低的一方控制的),故需要用中间的组件把磁盘数据先到不同级别的缓存中,最终到达寄存器
举例:假设我在QQ上发消息给我朋友,那么整个传输过程是咋样的
键盘(输入单元)存储器
cpu
储存器
网卡(在电脑上可以看到消息,可理解为存储器到显示器也刷了一下)
朋友网卡
存储器
cpu
储存器
显示器
2、什么是操作系统(OS)?
OS:进行软硬件资源管理的软件,狭义上指的是(内核kernel),主要为进程管理、文件管理、驱动管理、内存管理。
如何理解操作系统的管理?
上述很好的展现了相关处理工作,即将相关信息抽取出来放入结构体中(先描述),再将结构体链接起来把表头交给操作系统(在组织),形象些说管理就是“先描述,在组织”。
3、为什么要用操作系统(OS)?
1、OS方便用户使用,对上给用户,开发人员,各种使用者,提供一个良好的运行环境
2、OS对下,管理好底层的相关软硬件资源,能够充分高效的使用这些资源
具体情况可根据整个计算机的层状结构展现,如下图所示在整个层状结构中,任何访问硬件或者软件的行为,必须通过OS接口,贯穿OS进行访问操作
个人写的C/C++代码,通常指的是开发操作+lib。系统调用,指的是系统提供的接口,可供开发使用。
库函数:语言或者第三方库给我门提供的接口。这些接口有些是对系统接口进行了一层封装例如printf函数,当然还有并未使用系统接口的函数。
4、进程概念
课本概念:程序的一个执行实例,正在执行的程序等。内核观点:担当分配系统资源(CPU时间,内存)的实体。
简单点说对于我们创建的进程通常是:进程 = 我们的程序 + 内核申请的数据结构(PCB)
PCB:用于描述进程,进程的相关信息放在进程控制块的数据结构(PCB)中,可以理解为进程属性的合集。Linux系统是用C语言编写的,Linux中的PCB通常为task_struct。
task_struct:Linux内核的一种数据结构,他会被装载到RAM(内存)里并且包含着进程的信息。其内容分类如下。
- 标识符:描述本进程的唯一标识符,用来区别其他进程。
- 状态:任务状态,退出代码,退出信号等。
- 优先级:相对于其他进程的优先级。
- 程序计数器:程序中即将被执行的下一条指令的地址。
- 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。
- 上下文数据:进程执行时处理器的寄存器中的数据。
- I/O状态信息:包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
- 记账信息:包括处理器时间总和,使用的时钟数总和,时间限制,记帐号等。
- 其他信息。
5、为什么要存在PCB呢?
6、进程在CPU上运行时,相关概念及理解
1、进程放在CPU上之后,不是一直在运行直到进程运行结束,每个进程都有一个运行时间单位时间片,一旦时间片到了该进程先暂停
2、进程让出CPU的可能情况:a、来了一个优先级更高的进程 b、时间片到了
3、单CPU,单核:跑起来多个进程,通过进程快速切换的方式,在一段时间内,让所有的进程代码都得到推进,并发!
4、多CPU、多核:任何时刻,允许多个进程同时执行,并行!
7、进程切换中的硬件上下文
CPU中寄存器存储的数据称为硬件上下文。当一个进程由于某些原因要暂时停止执行(比如时间片到了),让出CPU时,要把当前进程的上下文数据保存到进程控制块(task_struct)中,让CPU执行其他进程,当恢复执行进程时,把控制块中的上下文数据恢复到对应寄存器中继续执行。
8、理解fork()函数
父进程通过调用fork函数创建一个子进程,两者并不完全相同。调用fork函数会返回两个值,在父进程中,fork返回子进程的PID,在子进程中fork返回0。通过返回值不同,可以确定谁在执行程序,也可通过返回值让父子执行不同的程序。
程序员角度:父子共享用户代码,数据各有一份。这是由于代码不可修改,数据可以修改。实际上数据通常也是共用的,只不过当子进程修改数据时,发生写时拷贝(与进程地址空间有关系)。
内核角度:创建子进程,通常以父进程为模板,其实就是多了一个进程控制块,其指向父进程代码和数据,这里的子进程私有一份数据,也只是当修改数据时发生写时拷贝,不修改时其实其指向的是同一份数据。
为啥存在两个返回值呢?可以理解为当fork创建子进程之后,子进程立马添加到了运行队列,此时return 还未执行,由于共享代码,所以子进程也执行了return,故存在两个返回值。
9、进程状态
Linux内核中进程有不同的状态
1、R运行状态:运行状态并不是一定要运行,只要进程在运行队列中,就叫做运行状态。
2、S睡眠状态:进程正在等待某件事完成,也叫浅度睡眠或者可终断睡眠。大部分我们所写均是S状态,原因很简单CPU运行速度极快,我们创建的进程在CPU上运行时间很短。
3、D磁盘休眠状态:深度睡眠,有时也叫不可中断睡眠状态,在这个状态进程通常会等待IO的结束。需要指出:系统创建进程,从内存往磁盘上写数据,此时操作系统不可以把进程杀掉,因为一旦杀掉数据写入磁盘成功与否无法判断。只能等待进程退出,其退出时会将自己退出的相关信息写入PCB中,供父进程或者OS进行读取,读取成功后才算正真死亡!
4、T停止状态:可以通过发送SIGSTOP信号来停止T进程。也可发送信号恢复停止进程,继续运行
5、X死亡状态:这个状态只是一个返回状态,你不会在列表中看到这个状态
两种特殊进程:
Z状态:处于Z状态的进程叫做僵尸进程。当子进程退出,但是父进程没有读取到子进程退出的返回代码就会产生僵尸进程(子进程为僵尸进程)。僵尸进程一直以终止状态保持在进程表中,并且一直在等待父进程读取退出状态代码。
僵尸进程的危害:
- 由于必须要告诉关系他的父进程交给他的任务完成的咋样,所以进程退出状态必须维持下去,父进程一直不读取,只能一直处于Z状态
- 维护退出状态也要数据维护,也属于进程基本信息,保存在task_struct中。故一直不退出,僵尸进程一直都在,PCB(task_struct)一直都在
- 一个父进程创建了许多子进程,不回收,浪费许多内存资源。并且我们不进行malloc时,结构体创建位于栈区
- 内存泄露
孤儿进程:如果父进程先退出,子进程只能由一号进程接管,称为孤儿进程。
10、进程优先级
优先级:资源有限,故想要得到资源得有先后顺序
与权限的区别:(权限:指能不能得到某种资源)
优先级越小,优先级越高。每次修改优先级只是在基准值上加减。pri = pri(old) + nice,80 + 【-20,19】,其中pri(old)每次设置时都是80
为啥要将old设置为一个基准值80呢?方便调整,避免每次还得计算之前优先级。设计上简单。
为啥存在优先级呢?OS内的调度器,要“公平”且高效的调度。注意这里的公平不是平均,是为了每个进程都能跑,但是大家并不是平均的跑。
如何修改:可通过top + r,之后写入进程pid,填入nice值,修改pri