操作系统--持续更新

操作系统
1,进程线程
2,锁
3,虚拟地址,

高频知识点:
进行和线程

- 进程和线程的概念
进程是对运行时程序的封装,是系统进行资源调度和分配的基本单位,实现操作系统的并发(???),
线程是进程的子任务,是CPU调度和分派的基本单位,用于保证程序的实时性,实现进程内部的并发。线程是操作系统内部可识别的最小执行和调度单位。每个线程都独自占用一个虚拟处理器,独自的寄存器组,指令计数器和处理器状态。虽然每个线程完成不同的任务,但是共享一篇地址空间(同样的动态内存,映射文件,目标代码等),打开的文件队列和其他内核资源。
- 二者有何区别。
①依赖性。线程依赖进程而存在。线程和进程是N:1的关系。
②最小单位。进程是资源分配的最小单位,线程是CPU调度的最小单位。
③拥有的内存资源。进程在执行过程中有独立的内存单位,而多个线程共享进程的内存。(资源分配给进程,同一个进程中所有的线程享有该进程的所有资源。同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储),但是每个线程都有自己的栈段(运行时段,用来存放所有的局部变量和临时变量))。
④系统开销。创建和切换进程的开销要远大于线程的开销。因为只要是涉及到进程的,系统都要为之分配/回收内存,如内存空间,I/O设备等。在切换进程时,涉及到整个当前的CPU环境的保存以及新被调度运行的进程的CPU环境的设置。而线程的切换只需保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作。
⑤通信。线程间通信比进程间通信要容易一些。同一进程间的多个线程有相同的地址空间,所以它们之间的同步和通信的实现比较容易。进程间通信IPC。线程间可以直接读写进程数据段(全局变量**)来进行通信-为了保障数据的一致性,需要一定的进程的同步和互斥的手段。(???后续补充)。在右的系统中,线程的切换、同步和通信都需要操作系统内核的干预。
⑥调试的复杂程度。进程编程调试简单可靠性高,但是创建销毁开销大;线程开销小,切换速度快,但是编程调试相对复杂。
进程之间不会互相影响,但是进程中的一个线程挂掉会导致整个进程挂掉(???**)
⑧进程适应于多核,多机分布;线程适应于多核。

- 进程间如何通信

管道,系统IPC(消息队列,信号量,信号,共享内存)、套接字socket。
① 管道
管道用于具有血缘关系的父子进程间的通信,主要包括有名管道和无名管道。有名管道除了有管道的功能呢,还允许无亲缘关系进程间的通信。
(1,1)普通管道PIPE
半双工(数据只能在一个方向上流动),有固定的读端和写端。
只能用于具有亲缘关系的进程间的通信(父子/兄弟进程之间)
并不属于任何其他文件系统, 只存在与内存中,可以看成是一种特殊的文件,读写依然可以使用read,write。
(1,2)命名管道FIFO
可在无关数据之间进行数据交换。
以一种特殊设备文件形式存在在文件系统中。
②系统IPC
(2.1)消息队列
消息的链接表,存在内核中。一个消息队列由一个标识符(队列ID)来标记。有写权限的进程可按照一定规则向消息队列中添加新信息,有读的权限可以从消息队列中读信息。
消息队列克服了信号传输信息少,管道只能承载无格式字节流以及缓冲区大小受限等特点。
特点:
面向记录,其中的消息有特定的格式以及特性的优先级。
独立于发送和接收进程。进程终止时,消息队列和内容并不会被删除。
支持随机查询。消息不一定要先进先出,也可以按消息的类型读取。
(2.2)信号量
是一个计数器,用来控制多个进程对共享资源的访问。信号量用于实现进程间的互斥和同步,而不是用于存储进程间通信数据。
特点:
用于进程间同步,若要在进程间传递数据需要结合共享内存。
信号量基于操作系统的PV操作,程序对信号量的操作都是原子操作。
每次对信号量的PV操作不仅限于对信号量+1或-1,而且可以加减任意正整数。
支持信号量组。
(2.3)信号Signal
是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
(2.4)共享内存
多个进程可以共享一块内存,不同进程可以及时看到对方进程中对共享内存中的数据的更新,依靠互斥锁和信号量来实现同步。
特点:
最快的IPC,因为是直接对内存进行读取。
多个进程可以同步,所以需要同步。
信号量+共享内存通常一起使用,信号量用来同步对共享内存的访问。

③套接字Socket
可以用于不同主机之间的进程通信。

线程间通信
临界区:通过多线程的串行化来访问公共资源或一段代码,速度快,时刻控制数据访问。
互斥量:只有拥有互斥对象的线程才有访问公共资源的权限,通过互斥对象只有一个,可以保障公共资源不会被多个线程同时访问。
信号量:为控制具有有限数量的用户资源而设计的,允许多个线程在同一时刻访问同一资源,但一般需要限制同一时刻访问此资源的最大线程数目。
事件,wait/notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。

各自又是怎样同步的。尚未写

  • 为什么要有线程和进程。
  • 多线程的多种方式,就绪状态的进程在等待什么
  • 僵尸进程
  • 怎样实现线程池
  • 线程间如何通信
  • 线程池

并发和并行

并发:
宏观上看起来是两个程序同时运行,比如单核cpu上的多任务。但是微观上的指令是交织运行的,指令互相穿插,你中有我,我中有你。在单个周期内只运行一个指令。这种并发并不能提高计算机的性能,只能提高效率。
并行:
严格物理意义上同时运行,比如多核CPU。两个程序分别运行在两个核上,两者互不影响。单个周期内每个程序都运行了自己的指令,也就是同时运行两个指令。这样是提高了运行的效率,现在CPU都是多核发展。

临界区
两个进程访问临界区资源,会不会出现都获得自旋锁的情况?
假设临界区资源释放,如何保障

怎样实现线程池

c++锁的机制。常用的锁
互斥锁和读写锁的区别。
互斥锁。mutex,用于保证任何时刻,都只能有一个线程访问该对象。当获取锁操作失败时,线程会进入睡眠,等待锁释放时被唤醒。
**读写锁。**rwlock,分为读锁和写锁。处于读操作时,可以允许多个线程同时获得读操作。但是同一时刻只能有一个线程获得写反馈。
互斥锁和写锁的区别:
读写锁区分读者和写者,而互斥锁不区分。
互斥锁同一时间只允许一个线程访问该对象,无论读写,读写锁的话。。你懂得。
条件变量
自旋锁

死锁产生的必要条件

Linux虚拟地址空间
为了防止不同进程同一时刻在物理内存的争夺,采用虚拟内存。
虚拟内存技术使得不同进程在运行过程中,它所看到的是自己独占了当前系统的的4G内存。所有进程共享同一物理内存,每个进程只把自己目前所需的虚拟聂村空间映射并存储到物理内存上。事实上,在每个进程创建加载时,内核只是为进程“创建”了虚拟内存的布局,具体就是初始化进程控制表内存相关的链表,实际并不立即把虚拟内存对应位置的程序数据和代码(text,data)拷贝到物理内存中,只是建立好虚拟内存和磁盘文件之间的映射就好(存储器映射),等到运行到对应的程序时,才会通过缺页异常来拷贝数据。还有进程运行过程中,要动态分配分配内存,比如malloc,也只是分配了虚拟内存,即为这块虚拟内存对应的页表项做对应设置,当进程真正访问此数据时,才引发缺页异常(???)
请求分页系统、请求分段系统和和请求段页式系统都是针对虚拟内存的,通过请求实现内存与外存的信息转换。

虚拟内存的好处。

  • 扩大地址空间。
  • 节省内存。当不同的进程使用同样的代码时,比如库文件中的代码,物理内存够中可以只存储一份这样的代码,不同的进程只需要把自己的虚拟内存映射过去就可以了。
  • 内存保存。每个进程运行在各自的虚拟内存地址空间,互相不能干扰对方。虚拟还对特定的内存地址提供写保护,可以防止代码或数据被恶意篡改。
  • 公平内存分配。采用了虚存之后,每个进程都相当于有同样大小的虚存空间。
  • 当进程通信时,可采用虚存共享的方式实现。
  • 提高了系统并发度。虚拟内存很适合在多道程序设计系统中使用,许多程序的片段同时保存在内存中。当一个程序等待它的一部分读入内存时,可以把CPU交给另一个进程使用。在内存中可以保留多个进程。
  • 利用碎片。当程序需要分配连续的内存空间时,只需要在虚拟内存空间连续分配空间,而不需要实际物理内存的连续空间。

虚拟内存的代价。

  • 这些数据结构需占用额外的内存+如果一页中只有一部分数据,虚存的管理需要建立很多的数据结构。
  • 增加指令的执行时间。虚拟地址到物理地址的转换+页面的换入换出需要磁盘I/O.

操作系统中的程序的内存结构,虚拟内存和物理内存如何对应,虚拟内存置换的方式
在这里插入图片描述
一个程序本质上都是由BSS段,data段,text段三个组成的。 可以看到一个可执行程序在存储(没有调入内存)时分为代码段,数据库和未初始化数据区三部分。
BSS段(未初始化数据区):通常用来存放程序为出初始化的全局变量和静态变量。BSS段数据静态分配,程序结束后静态变量资源由系统自动释放。
数据段:存放程序中已初始化的全局变量的一块内存区域。数据段也属于静态数据分配
代码段:存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域属于只读。在代码段中,也有可能包含一些只读的常熟变量。
text段和data段在编译时已经分配了空间,而BSS段并不占用可执行文件的大小,它是由链接器来获取内存的。
BSS段:未经初始化的数据并不存放在磁盘上的程序文件中。原因是内核在程序开始运行前将他们设置为0,需要存放在程序文件中的只有正文段和初始化数据段。
data 段:已经初始化的数据,被分配空间,数据保存在目标文件中。
数据段包含经过初始化的全局变量以及它们的值。BSS段的大小从可执行文件中得到,然后链接器得到这个大小的内存块,紧跟在数据段的后面。当这个内存进入程序的地址空间后全部清零。包含数据段和BSS的整个区段此时通常称为数据区。
可执行程序在运行时又多出两个区:栈和堆。
:存放函数的入参,返回类型,局部变量等信息,当一个函数被调用时,函数的的一些信息就会被存放到栈中。然后这个被调用的函数再为它的自动变量和临时变量在栈上分配空间。栈是一个连续的内存区域,最大容量由系统预先定义好,从高地址向低地址增长,没调用一个函数一个新的栈就会被使用。申请的占空间超过这个界限就会提示溢出。
堆区:用于动态内存分布。位于BSS和栈中间的地址区域。程序员申请分配和释放。堆是从低地址向高地址位增长,采用链式存储结构。频繁的malloc/free造成内存空间的不连续,产生碎片。当申请堆空间时库函数是按照一定的算法搜索可用的足够大的空间。因此堆的效率要比栈低得多。

操作系统中的缺页中断

操作系统中的结构体对齐,字节对齐操作系统
对齐原因
平台原因:不是所有硬件平台都能访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出异常。
性能原因:数据结构(栈)应该尽可能在自然边界上对齐。为了访问未对齐的内存,处理器需要作两次内存访问,而对齐的内存只需要一次。

进程间如何通信
互斥锁*(mutex)机制,以及互斥锁和读写锁的区别

*A a = new A; a->i = 10.在内核中的内存分配上发生了什么

给一个类,有static,virtual,说一个这个类的内存分布

软连接和硬链接的区别

什么是大小端,如何判断大端和小端

静态变量如何初始化

用户态和内核态的区别

涉及server,使得能够接收多个客户端的请求

死循环+来链接时新建线程的方法效率低,如何改进

fork和vfork的区别,手撕fork调用示例

如何修改文件最大句柄数,什么是句柄数

并发和并行

操作系统中页数寻址

windows消息机制

内存溢出和内存泄漏

协程

系统调用,使用过哪些系统调用

用户态到内核态的转换原理

源码到可执行文件的过程

GDB调试,什么是条件断点

五种IO模型

异步变成的事件循环

操作系统为什么要分内核态和用户态

linux内核中的Timer定时器机制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值