一、内存管理
1.虚拟内存空间:为了在多进程环境下,使得进程之间的内存地址不受影响,相互隔离,于是操作系统就为每个进程独⽴分配⼀套虚拟地址空间。每个程序只关⼼⾃⼰的虚拟地址就可以,实际上⼤家的虚拟地址都是⼀样的,但分布到物理地址内存是不⼀样的。
2.内存交换技术:每个进程都有⾃⼰的虚拟空间,⽽物理内存只有⼀个,所以当启⽤了⼤量的进程,物理内存必然会很紧张,于是操作系统会通过内存交换技术,把不常使⽤的内存暂时存放到硬盘(换出),在需要的时候再装载回物理内存(换⼊)。
3.虚拟地址映射到物理地址(系统维护)
每一个进程都有4GB的虚拟地址空间!!!
1)内存分段:虚拟地址是通过段表与物理地址进行映射的
内存分段是根据程序的逻辑⻆度,分成了栈段、堆段、数据段、代码段等,这样可以分离出不同属性的段,同时是⼀块连续的空间。每一个段在段表中都有一个项,在这一项找到段的基地址在加上偏移量,于是就能找到物理内存的地址
缺点:但是每个段的⼤⼩都不是统⼀的,这就会导致内存碎⽚和内存交换效率低的问题(硬盘访问速度比较慢,这里如果出现内存碎片,就需要使用内存交换技术,那么这么一块数据写到硬盘时候,效率低下)。
2)内存分页 把虚拟空间和物理空间分成⼤⼩固定的⻚,比如在linux下每一个页是4K,因此不会产生细小的内存碎片。同时在内存交换的时候,写入硬盘也就是一页或者几个页,提高了交换的效率。
如果只有一级分页:需要覆盖整个4GB的话,需要100万个页,每个页表项4个字节,那么需要4MB的内存来存储页表。
多级页表:
以二级页表为例:首先我的一级页表可有1024个,内存仅需要4K,那么二级页表只有在需要的时候才创建。每一个一级页表上的一个页对应一个二级页表,所以二级页表也有1024个。那么总的对应起来一共也是100万个。 只是二级在创建的时候才使用。
1024个二级也是4MB,但是请注意,这是最极端的情况,就是虚拟内存表中4GB的数据同时都用到了。
缺点:多级页表,寻址的时候需要多层表的参与,时间开销大。根据程序局部性原理,在CPU中加入了TLB,复杂缓存最近常被访问的页表项,大大提高了地址的转换速度。
3)段页式内存管理 组合起来
第⼀次访问段表,得到⻚表起始地址;
第⼆次访问⻚表,得到物理⻚号;
第三次将物理⻚号与⻚内位移组合,得到物理地址。
4)Linux主要用分页管理。
另外,Linxu 系统中虚拟空间分布可分为⽤户态和内核态两部分,其中⽤户态的分布:代码段、全局变量、BSS(为初始的全局)、函数栈、堆内存、映射区。
二、进程和线程
1.进程:运行中的程序
1)单核CPU中某一瞬间只能运行一个线程,但是1秒中期间,可能运行多个进程,产生并行的错觉(这种是至多CPU同时处理的感觉),实际上是并发(交替进行)。
2)进程的状态:
就绪:可运⾏,由于其他进程处于运⾏状态⽽暂时停⽌运⾏; 等待CPU资源
阻塞:该进程正在等待某⼀事件发⽣(如等待输⼊/输出操作的完成)⽽暂时停⽌运
⾏,这时,即使给它CPU控制权,它也⽆法运⾏;
运行:该时刻进程占⽤ CPU
就绪--》 运行:就是指此时被进程的调度器选中
运行-》就绪:配分的时间片用完了
运行-》阻塞:等待某个时间 比如I/O
阻塞-》就绪:就是等待时间完成,但是需要CPU资源调度,所以是就绪
请注意阻塞无法直接运行 需要就绪 然后 运行
3)PCB进程控制块--这是进程存在的唯一标识
包含进程标识符、进程当前状态、优先级、有缘虚拟地址空间信息 以及CPU中各个寄存器的值
每个PCB组织
利用链表方式:实现就绪队列 阻塞队列
4)进程上下文切换:一个进程切换到另外一个进程
CPU 上下⽂切换就是先把前⼀个任务的 CPU 上下⽂(CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下⽂到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运⾏新任务。
切换:虚拟内存 栈 全局变量 内核堆栈 寄存器
2.线程:
1)进程是资源分配的单位,线程是CPU调度的单位
进程线程区别:
进程拥有完整的资源平台,但是线程只独享不可少的资源,如寄存器和栈
因此线程能够减少并发执行的时间和空间开销

3.调度;选择⼀个进程运⾏这⼀功能是在操作系统中完成的,通常称为调度程序(scheduler)。
3.进程间通信
每个进程的用户地址空间是独立的,不能互相访问,但是内核空间每个进程是共享的,所以进程之间通信需要通过内核。
1)管道:
匿名管道:返回两个文件描述符,一个读一个写 仅存在于内存 不存在于文件系统
条件:通信范围是父子关系的进程 因为没有实体
子进程会复制父进程的文件描述符
有名管道:可以实现无关系的进程通信 创建一个设备文件
缺点:前⾯说到管道的通信⽅式是效率低的,因此管道不适合进程间频繁地交换数据。、
并且一个管道只能实现 一端读 一端写 单项的


2)消息队列
A 进程要给 B 进程发送消息,A 进程把数据放在对应的消息队列后就可以正常返回了,B 进程需要的时候再去读取数据就可以了。
两个进程之间的通信就像平时发邮件⼀样,你来⼀封,我回⼀封,可以频繁沟通了。
缺点:⼀是通信不及时,⼆是附件也有⼤⼩限制(内核消息体有最大长度的限制)
三消息队列通信过程中,存在⽤户态与内核态之间的数据拷⻉开销

3)共享内存:
共享内存的机制,就是拿出⼀块虚拟地址空间来,映射到相同的物理内存中。这样这个进程写⼊的东⻄,另外⼀个进程⻢上就能看到了,都不需要拷⻉来拷⻉去,传来传去,⼤⼤提⾼了进程间通信的速度。

多个进程同时修改一个共享内存,容易冲突
但是可以使用信号量来进行保护资源 实现进程间的同步
4)信号 信号是进程间通信机制中唯⼀的异步通信机制 ,因为可以在任何时候发送信号给某⼀进程
SIGINT 信号,表示终⽌该进程
SIGTSTP 信号,表示停⽌该进程,但还未结束
SIGKILL 信号,⽤来⽴即结束该进程;
处理方式:默认 捕捉 忽略

5)套接字socket:这是跨网络与不同主机上的进程之间的通信

一个是监听的套接字,后面accept会生成用于传输数据的socket
本地 socket 被⽤于在同⼀台主机上进程间通信的场景
而对于线程只要是共享变量都可以做到线程间通信,关注的不是通信方式,而是多线程竞争贡献资源的问题。
4.死锁:
-
两个或两个以上的进程在执行过程中,因争夺共享资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁
几种场景:
忘记释放锁
重复加锁
多线程多锁,抢占锁资源:线程 A 和 线程 B,然后有两个互斥锁,分别是 mutex_A 和
mutex_B。线程A获取锁顺序显示锁A 然后想去争取锁B 但是线程B是获取锁B 然后获取锁A
可以看到线程 B 在等待互斥锁 A 的释放,线程 A 在等待互斥锁 B 的释放,双⽅都在等待对⽅资源的释放,很明显,产⽣了死锁问题。
死锁只有同时满⾜互斥、持有并等待、不可剥夺、环路等待这四个条件的时候才会发⽣。
解决死锁:破坏上面其中一个条件就可以 资源有序分配法
线程 A 和 线程 B 获取资源的顺序要⼀样,当线程 A 是先尝试获取资源 A,然后尝试获取资源 B 的时候,线程 B 同样也是先尝试获取资源 A,然后尝试获取资源 B。也就是说,线程 A 和 线程 B 总是以相同的顺序申请⾃⼰想要的资源。
5685

被折叠的 条评论
为什么被折叠?



