操作系统1

  1. OS Kernel的特征
    1.1 并发
    1.2 共享:“同时访问”,互斥共享
    1.3 虚拟:利用多道程序设计技术,让每个用户都觉得有一个计算机专门为他服务
    1.4 异步:程序的执行不是一贯到底,而是走走停停,向前推荐的速度不可预知,但只要运行环境相同,OS需要保证程序的每次运行结果也相同
  2. 系统调用(来源于应用程序)(同步或异步)
    应用程序主动向操作系统发出服务请求
  3. 异常(来源于不良的应用程序)(同步)
    非法指令或者其他坏的处理状态(如:内存出错)
  4. 中断(来源于外设)(异步,不知道什么时候产生)
    来自不同的硬件设备的计时器或网络中断
  5. 中断处理机制:
    硬件:设置中断标记(将内部、外部事件设置中断标记,中断事件的ID)
    软件(操作系统):保存当前处理状态,中断服务程序处理,清除中断标记,恢复之前保存的处理状态
  6. 异常处理机制:
    保存现场、异常处理(杀死了产生异常的程序,重新执行异常指令),恢复现场
  7. 进程控制块PCB是进程存在的唯一标志
  8. 进程创建:系统初始化时;用户请求创建一个新进程;正在运行的进程执行了创建进程的系统调用
  9. 进程运行
  10. 进程等待
  11. 进程唤醒:只能被其他进程或操作系统唤醒
  12. 进程结束:正常退出;错误退出;致命退出(强制性的);被其他进程所杀(强制性的)
  13. 进程的三种基本状态:进程在生命结束前处于且仅处于三种基本状态之一: 运行状态(running):当一个进程处在处理机上运行时;就绪状态(ready):一个进程获得了除处理机之外的一切所需资源,一旦得到处理机即可运行;等待状态(又称阻塞状态):一个进程正在等待某一事件而暂停运行时,如等待某资源,等待输入/输出完成
    在这里插入图片描述
  14. 挂起状态:在硬盘上
  15. 线程所需的资源
    在这里插入图片描述
  16. 进程和线程的区别
    进程是资源分配单位,线程是CPU调度单位
    进程拥有一个完整的资源平台,而线程只独享必不可少的资源,如寄存器和栈
    线程同样具有就绪,阻塞和执行三种基本状态,同样具有状态之间的转换关系
    线程能减少并发执行的时间和空间开销:线程的创建和终止时间比进程短;同一进程内的线程切换时间比进程短;由于同一进程的各线程共享内存和文件资源,可直接进行不通过内核的通信
  17. 线程的实现:用户线程,内核线程
  18. 进程的创建:fork():创建一个继承的子进程,复制父进程的所有变量和内存,复制父进程的所有CPU寄存器,子进程的fork()返回0,父进程的fork()返回子进程标识符,fork()返回值可方便后续使用,子进程可使用getpid()获取PID
    在这里插入图片描述
    在这里插入图片描述
  19. 竞态条件:系统缺陷:结果依赖于并发执行或者事件的顺序/时间,有不确定性和不可重现性;怎样避免竞态:让指令不被打断
  20. 原子操作
  21. 临界区:指进程中的一段需要访问共享资源并且当另一个进程处于相应代码区域时便不会被执行的代码区域
  22. 互斥:当一个进程处于临界区并访问共享资源时,没有其他进程会处于临界区并且访问任何相同的共享资源
  23. 死锁:两个或以上的进程,在相互等待完成特定任务,而最终没法将自身任务进行下去
  24. 饥饿:一个可执行的进程,被调度器持续忽略,以至于虽然处于可执行状态却不被执行
  25. 在这里插入图片描述
  26. 信号量:P操作会进行堵塞(当值小于0时)
    在这里插入图片描述
  27. 管程:一个锁,0个或多个条件 变量
  28. 死锁处理办法:死锁预防,死锁避免(银行家算法),死锁检测,死锁恢复
  29. 虚拟内存:虚拟内存是将系统硬盘空间和系统实际内存联合在一起供进程使用,给进程提供了一个比内存大得多的虚拟空间。在程序运行时,只要把虚拟地址空间的一小部分映射到内存,其余都存储在硬盘上(也就是说程序虚拟空间就等于实际物理内存加部分硬盘空间)。当被访问的虚拟地址不在内存时,则说明该地址未被映射到内存,而是被存贮在硬盘中,因此需要的虚拟存储地址随即被调入到内存;同时当系统内存紧张时,也可以把当前不用的虚拟存储空间换出到硬盘,来腾出物理内存空间。 MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,是一个硬件
    在保护模式下,控制寄存器CR0的最高位PG位控制着分页管理机制是否生效,如果PG=1,分页机制生效,需通过页表查找才能把线性地址转换物理地址。如果PG=0,则分页机制无效,线性地址就直接做为物理地址。
    分页的基本原理是把内存划分成大小固定的若干单元,每个单元称为一页(page),每页包含4k字节的地址空间(为简化分析,我们不考虑扩展分页的情况)。这样每一页的起始地址都是4k字节对齐的。为了能转换成物理地址,我们需要给CPU提供当前任务的线性地址转物理地址的查找表,即页表(page table)。注意,为了实现每个任务的平坦的虚拟内存,每个任务都有自己的页目录表和页表。
    为了节约页表占用的内存空间,x86将线性地址通过页目录表和页表两级查找转换成物理地址。
    32位的线性地址被分成3个部分:最高10位 Directory 页目录表偏移量,中间10位 Table是页表偏移量,最低12位Offset是物理页内的字节偏移量。
    页目录表的大小为4k(刚好是一个页的大小),包含1024项,每个项4字节(32位),项目里存储的内容就是页表的物理地址。如果页目录表中的页表尚未分配,则物理地址填0。
    页表的大小也是4k,同样包含1024项,每个项4字节,内容为最终物理页的物理内存起始地址
    每个活动的任务,必须要先分配给它一个页目录表,并把页目录表的物理地址存入cr3寄存器。页表可以提前分配好,也可以在用到的时候再分配。
    我们知道Linux中用户进程线性地址能寻址的范围是0 - 3G,那么是不是需要提前先把这3G虚拟内存的页表都建立好呢?一般情况下,物理内存是远远小于3G的,加上同时有很多进程都在运行,根本无法给每个进程提前建立3G的线性地址页表。Linux利用CPU的一个机制解决了这个问题。进程创建后我们可以给页目录表的表项值都填0,CPU在查找页表时,如果表项的内容为0,则会引发一个缺页异常,进程暂停执行,Linux内核这时候可以通过一系列复杂的算法给分配一个物理页,并把物理页的地址填入表项中,进程再恢复执行。当然进程在这个过程中是被蒙蔽的,它自己的感觉还是正常访问到了物理内存。
    linux进程的内存布局的每个段都是有一个vm_area_struct,而这个实例是由连续的虚拟内存地址组成;
    当请求内存时,先是扩展vm_area_struct或者新分配一个vm_area_struct,但是并不映射物理内存,只有等到访问这块内存时,产生缺页异常,内核才分配物理内存。
    在这里插入图片描述
    (1)页是信息的物理单位,分页是为了实现非连续分配,以便解决内存碎片问题,或者说分页是由于系统管理的需要.段是信息的逻辑单位,它含有一组意义相对完整的信息,分段的目的是为了更好地实现共享,满足用户的需要(数据段,代码段).
    (2)页的大小固定,由系统确定,将逻辑地址划分为页号和页内地址是由机器硬件实现的.而段的长度却不固定,决定于用户所编写的程序,通常由编译程序在对源程序进行编译时根据信息的性质来划分.
    (3)分段机制使用大小可变的块,更适合处理复杂系统的逻辑分区,分段是将逻辑地址变为线性地址,分页是将线性地址变为物理地址,但是现在基本上逻辑地址等于线性地址
    要动态分配内存,比如malloc时,也只是分配了虚拟内存,即为这块虚拟内存对应的页表项做相应设置,当进程真正访问到此数据时,才引发缺页异常。
    请求分页系统、请求分段系统和请求段页式系统都是针对虚拟内存的,通过请求实现内存与外存的信息置换。
    虚拟内存的好处:
    1.扩大地址空间;
    2.内存保护:每个进程运行在各自的虚拟内存地址空间,互相不能干扰对方。虚存还对特定的内存地址提供写保护,可以防止代码或数据被恶意篡改。
    3.公平内存分配。采用了虚存之后,每个进程都相当于有同样大小的虚存空间。
    4.当进程通信时,可采用虚存共享的方式实现。
    5.当不同的进程使用同样的代码时,比如库文件中的代码,物理内存中可以只存储一份这样的代码,不同的进程只需要把自己的虚拟内存映射过去就可以了,节省内存
    6.虚拟内存很适合在多道程序设计系统中使用,许多程序的片段同时保存在内存中。当一个程序等待它的一部分读入内存时,可以把CPU交给另一个进程使用。在内存中可以保留多个进程,系统并发度提高
    7.在程序需要分配连续的内存空间的时候,只需要在虚拟内存空间分配连续空间,而不需要实际物理内存的连续空间,可以利用碎片
    虚拟内存的代价:
    1.虚存的管理需要建立很多数据结构,这些数据结构要占用额外的内存
    2.虚拟地址到物理地址的转换,增加了指令的执行时间
    3.页面的换入换出需要磁盘I/O,这是很耗时的
    4.如果一页中只有一部分数据,会浪费内存。
  30. 内存分布
    在这里插入图片描述
    一、首先进程地址空间的 1G 内核空间是给操作系统使用的,我们用户是没有操作权限的。
    二、剩下的 3G 内存空间中,分为了栈区、内存映射段、堆区、数据段、bss段、代码段
    1)栈区:这里的栈和数据结构的栈并不相同,数据结构的栈是一种后进先出的数据结构,而内存划分的栈是操作系统按照栈的特性,给用户划分出的内存区间。
       栈区一般存放:函数体的局部变量、函数调用期间的所有参数压栈、函数的返回值
    注意栈区这段内存是由操作系统自己维护的,所以函数结束,在栈上的空间会由操作系统自己回收。
    2)堆区:用户所操作的内存就是堆上的空间,用户可以使用 malloc / calloc / realloc / new 申请堆上的空间,但是用户申请堆上的空间必须自己手动释放,不然会造成内存泄漏。
    3)内存映射段:里面存放 动态库 / 静态库,以及文件映射,匿名映射等等一切有依赖性的东西都在这段区域
    4)一个程序本质上都是由 bss段、数据段、代码段组成的
       数据段:存放全局变量、静态类型的变量。当代码编译完后,在可执行程序这个文件中已经把这些数据的空间划分好了,这种类型的数据,在程序运行以前,操作系统就将数据段中的数据加载到内存了。也就是说在进入 main 函数之前这些数据已经划分号空间了。
       bss段:其实在 C 语言中,数据段中还有一个 bss 段,这里面存放的是未初始化的全局变量和静态数据,而数据段中存放的是已经初始化过的全局变量和静态数据。数据段中的所有数据已经划分好空间了,但是 bss 段并没有给其中的数据划分空间。
       代码段:存放可执行代码,以及只读常量(字符串常量等等)。这段内存是只读的。
    参见 https://blog.csdn.net/Code_beeps/article/details/89608929
  31. 线程和进程
    1.一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程依赖于进程而存在。
    2.进程在执行过程中拥有独立的内存单元,而多个线程共享进程的内存。(资源分配给进程,同一进程的所有线程共享该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量。)
    3.进程是资源分配的最小单位,线程是CPU调度的最小单位;
    4.系统开销: 由于在创建或撤消进程时,系统都要为之分配或回收资源,如内存空间、I/o设备等。因此,操作系统所付出的开销将显著地大于在创建或撤消线程时的开销。类似地,在进行进程切换时,涉及到整个当前进程CPU环境的保存以及新被调度运行的进程的CPU环境的设置。而线程切换只须保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作。可见,进程切换的开销也远大于线程切换的开销。
    5.通信:由于同一进程中的多个线程具有相同的地址空间,致使它们之间的同步和通信的实现,也变得比较容易。进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。在有的系统中,线程的切换、同步和通信都无须操作系统内核的干预
    6.进程编程调试简单可靠性高,但是创建销毁开销大;线程正相反,开销小,切换速度快,但是编程调试相对复杂。
    7.进程间不会相互影响 ;线程一个线程挂掉将导致整个进程挂掉
  32. 进程间通信和线程间通信
    进程间通信:信号,管道,消息队列,共享内存
    线程间通信:临界区:通过多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问;互斥量Synchronized/Lock:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问;信号量Semphare:为控制具有有限数量的用户资源而设计的,它允许多个线程在同一时刻去访问同一个资源,但一般需要限制同一时刻访问此资源的最大线程数目。事件(信号),Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作
  33. 请你说一说操作系统中的缺页中断
    malloc()和mmap()等内存分配函数,在分配时只是建立了进程虚拟地址空间,并没有分配虚拟内存对应的物理内存。当进程访问这些没有建立映射关系的虚拟内存时,处理器自动触发一个缺页异常。
    缺页中断:在请求分页系统中,可以通过查询页表中的状态位来确定所要访问的页面是否存在于内存中。每当所要访问的页面不在内存是,会产生一次缺页中断,此时操作系统会根据页表中的外存地址在外存中找到所缺的一页,将其调入内存。
    缺页本身是一种中断,与一般的中断一样,需要经过4个处理步骤:
    1、保护CPU现场
    2、分析中断原因
    3、转入缺页中断处理程序进行处理
    4、恢复CPU现场,继续执行
    但是缺页中断是由于所要访问的页面不存在于内存时,由硬件所产生的一种特殊的中断,因此,与一般的中断存在区别:
    1、在指令执行期间产生和处理缺页中断信号
    2、一条指令在执行期间,可能产生多次缺页中断
    3、缺页中断返回是,执行产生中断的一条指令,而一般的中断返回是,执行下一条指令。
  34. 线程产生的原因:
    进程可以使多个程序能并发执行,以提高资源的利用率和系统的吞吐量;但是其具有一些缺点:
    进程在同一时间只能干一件事,进程在执行的过程中如果阻塞,整个进程就会挂起,即使进程中有些工作不依赖于等待的资源,仍然不会执行。
    因此,操作系统引入了比进程粒度更小的线程,作为并发执行的基本单位,从而减少程序在并发执行时所付出的时空开销,提高并发性。和进程相比,线程的优势如下:
    从资源上来讲,线程是一种非常"节俭"的多任务操作方式。在linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种"昂贵"的多任务工作方式。
    从切换效率上来讲,运行于一个进程中的多个线程,它们之间使用相同的地址空间,而且线程间彼此切换所需时间也远远小于进程间切换所需要的时间。据统计,一个进程的开销大约是一个线程开销的30倍左右。
    从通信机制上来讲,线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过进程间通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进城下的线程之间贡献数据空间,所以一个线程的数据可以直接为其他线程所用,这不仅快捷,而且方便。
    除以上优点外,多线程程序作为一种多任务、并发的工作方式,还有如下优点:
    1、使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
    2、改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序才会利于理解和修改。
  35. 线程在切换的过程中需要保存当前线程Id、线程状态、堆栈、寄存器状态等信息。其中寄存器主要包括SP PC EAX等寄存器,其主要功能如下:
    SP:堆栈指针,指向当前栈的栈顶地址
    PC:程序计数器,存储下一条将要执行的指令
    EAX:累加寄存器,用于加法乘法的缺省寄存器
  36. 多线程模型主要优势为线程间切换代价较小,因此适用于I/O密集型的工作场景,因此I/O密集型的工作场景经常会由于I/O阻塞导致频繁的切换线程。同时,多线程模型也适用于单机多核分布式场景
    多进程模型,适用于CPU密集型。同时,多进程模型也适用于多机分布式场景中,易于多机扩展。
  37. 死锁是指两个或两个以上进程在执行过程中,因争夺资源而造成的下相互等待的现象。死锁发生的四个必要条件如下:
    互斥条件:进程对所分配到的资源不允许其他进程访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源;
    请求和保持条件:进程获得一定的资源后,又对其他资源发出请求,但是该资源可能被其他进程占有,此时请求阻塞,但该进程不会释放自己已经占有的资源
    不可剥夺条件:进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用后自己释放
    环路等待条件:进程发生死锁后,必然存在一个进程-资源之间的环形链
    解决死锁的方法即破坏上述四个条件之一,主要方法如下:
    资源一次性分配,从而剥夺请求和保持条件
    可剥夺资源:即当进程新的资源未得到满足时,释放已占有的资源,从而破坏不可剥夺的条件
    资源有序分配法:系统给每类资源赋予一个序号,每个进程按编号递增的请求资源,释放则相反,从而破坏环路等待的条件
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值