bug
,拓展性比较差,每次需要增加新的功能,都要将新的代码和原来的内核代码重新编译。 IPC
、地址空间分配和基本的调度,这些东西都在内核态运行,其他功能作为模块被内核调用,并且是在用户空间运行。微内核比较好维护和拓展,但是效率可能不高,因为需要频繁地在内核态和用户态之间切换。 Sharing time system
)就是系统把CPU
时间分成很短的时间片,轮流地分配给多个作业。它的优点就是对多个用户的多个作业都能保证足够快的响应时间,并且有效提高了资源的利用率。 Real-time system
)是系统对外部输入的信息,能够在规定的时间内(截止期限)处理完毕并做出反应。它的优点是能够集中地及时地处理并作出反应,高可靠性,安全性。 CPU
,从形势上实现多任务。各个用户/进程之间的调度并非精准度特别高,如果一个进程被锁住,可以给它分配更多的时间。而实时操作系统则不同,软件和硬件必须遵从严格的时间限制,超过时限的进程可能直接被终止。在这样的操作系统中,每次加锁都需要仔细考虑。 C
库(libc.so
) 通常就是动态链接的,这样所有的程序可以共享同一个库,而不用分别进行封装。 #
开头的预处理命令; printf.o
等单独预编译好的目标文件进行合并,得到最终的可执行目标文件。对于单核单线程CPU
而言,在某一时刻只能执行一条CPU
指令。上下文切换(Context Switch
)是一种将CPU
资源从一个进程分配给另一个进程的机制。从用户角度看,计算机能够并行运行多个进程,这恰恰是操作系统通过快速上下文切换造成的结果。在切换的过程中,操作系统需要先存储当前进程的状态(包括内存空间的指针,当前执行完的指令等等),再读入下一个进程的状态,然后执行此进程。
ANSI C
编译器版本中,C
库函数是相同的。 在两个或多个并发进程中,如果一个进程集合中的每个进程都在等待只能由该进程集合中的其他进程才能引发的事件,那么该进程集合就产生了死锁。
死锁产生的根本原因是多个进程竞争资源时,进程的推进顺序出现不正确。
对于死锁,主要有4
种解决策略。
鸵鸟策略
就是直接忽略死锁。就像鸵鸟遇到危险的时候,把头埋在沙子里,假装根本没发生问题。因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。大多数操作系统,包括 Unix
,Linux
和 Windows
,处理死锁问题的办法仅仅是忽略它。
死锁预防
死锁预防是指通过破坏死锁产生的四个必要条件中的一个或多个,以避免发生死锁。
死锁避免
为了避免因为预防死锁而导致所有线程变慢,死锁避免采用了与死锁预防相反的措施。它允许三个必要条件,但通过算法判断资源请求是否可能导致循环等待的形成并相应决策,来避免死锁点的产生。因此,其前提是知道当前资源使用的整体情况,以及申请资源线程本身所占有的资源细节。
判断和决策中,主要使用两种避免方法。
整体来看,死锁避免是从资源和线程相互间关系着手,避免形成循环等待是其主要任务。
死锁检测和恢复
可以允许系统进入死锁状态,但会维护一个系统的资源分配图,定期调用死锁检测算法来检测途中是否存在死锁,检测到死锁发生后,采取死锁恢复算法进行恢复。
死锁检测方法如下:
检测到死锁后,就需要解决死锁。目前操作系统中主要采用如下几种方法:
临界区是一段代码,在临界区内进程将访问临界资源。任何时候最多只有一个进程可以进入临界区,也就是说,临界区具有排他性。所以,为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查。
就是使用一个互斥的变量来直接制约多个进程,每个进程只有拥有这个变量才具有访问公共资源的权限,因为互斥量只有一个,所以能保证资源的正确访问。
信号量(Semaphore
)是一个整型变量,可以对其执行自增和自减操作,自减操作通常也叫做P
操作,自增操作也称为V
操作。这两个操作需要被设计成原语,是不可分割,通常的做法是在执行这些操作的时候屏蔽中断。进程使用这两个操作进行同步。
P
操作,如果执行操作后信号量小于 0
,那么执行该操作的进程就会阻塞,否则继续执行; V
操作,如果操作之后的信号量小于等于0
,那么就会从阻塞队列唤醒一个进程。 管程使用的是面向对象思想,将表示共享资源的数据结构还有相关的操作,包括同步机制,都集中并封装到一起。所有进程都只能通过管程间接访问临界资源,而管程只允许一个进程进入并执行操作,从而实现进程互斥。管程中设置了多个条件变量,表示多个进程被阻塞或挂起的条件。对条件变量执行 wait()
操作会导致调用进程阻塞,把管程让出来给另一个进程持有。signal()
操作用于唤醒被阻塞的进程。管程有一个重要特性,就是在一个时刻只能有一个进程使用管程。进程在无法继续执行的时候不能一直占用管程,否则其它进程永远不能使用管程。
这种管道也叫FIFO
。命名管道不同于管道的地方,在于它提供了一个路径名与之关联,以命名管道的文件形式存在于文件系统中,这样,即使与命名管道的创建进程不存在亲缘关系的进程,只要可以访问文件系统中的这个路径,就能够彼此通过命名管道相互通信。命名管道严格遵循先进先出原则的,不支持诸如数据随机定位。命名管道的名字存在于文件系统中,但内容存放在内存中。
消息队列是消息的链表,具有特定的格式,它是存放在内存里面的,并且每个消息队列都有唯一的标识。消息队列允许一个或多个进程向它写入与读取消息,所以,利用消息队列,一个进程可以将一个数据块发送到另一个进程,每个数据块都有一个类型,接收进程可以独立地接收含有不同类型的数据结构,这个过程是异步的,我们可以通过发送消息来避免命名管道的同步和阻塞问题。但消息队列的数据块有一个最大长度的大小限制。
IPC
形式。 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它是一种类似于锁的机制,就是防止某进程正在访问共享资源时,其他进程也访问该资源。参考这里。
Socket
就是套接字,套接字也是一种通信机制,凭借这种机制,可以让不在同一台主机上的两个进程,通过网络进行通信,一般可以用在客户端和服务器之间的通信。 Socket
是在应用层和传输层之间的一个抽象层,它把 TCP
/IP 协议的传输层里面复杂的操作,抽象为几个简单的接口,供应用层调用实现进程在网络中的通信。
Socket
,然后通过 Socket
对数据进行传输。通常服务器处于一个无限循环,等待客户端的连接。 Socket
,通过TCP
连接服务器,将 Socket
与远程主机的某个进程连接,然后就发送数据,或者读取响应数据,直到数据交换完毕,关闭连接,结束 TCP
对话。 Socket
,建立流式套接字,与本机地址及端口进行绑定,然后通知 TCP
,准备好接收连接,调用 accept()
阻塞,等待来自客户端的连接。如果这时客户端与服务器建立了连接,客户端发送数据请求,服务器接收请求并处理请求,然后把响应数据发送给客户端,客户端读取数据,直到数据交换完毕。最后关闭连接,交互结束。 TCP
连接的角度说说Socket通信流程。
首先是三次握手的Socket
交互流程。
socket()
、bind()
、listen()
完成初始化后,调用 accept()
阻塞等待; Socket
对象调用 connect()
向服务器发送了一个 SYN
并阻塞; SYN
和 ACK
应答; connect()
返回,再发送一个 ACK
给服务器; Socket
对象接收客户端第三次握手 ACK
确认,此时服务端从 accept()
返回,建立连接。 接下来就是两个端的连接对象互相收发数据。
然后是四次挥手的Socket
交互流程。
close()
主动关闭,发送一个 FIN
; FIN
后被动执行关闭,并发送 ACK
确认; close()
关闭 Socket
,并也发送一个 FIN
; FIN
的一端向另一端 ACK
确认。 SCAN
扫描算法。电梯算法就是说读写磁头总是保持一个方向运行,直到该方向没有请求为止,然后改变运行方向。 虚拟内存就是说,让物理内存扩充成更大的逻辑内存,从而让程序获得更多的可用内存。虚拟内存使用部分加载的技术,让一个进程或者资源的某些页面加载进内存,从而能够加载更多的进程,甚至能加载比内存大的进程,这样看起来好像内存变大了,这部分内存其实包含了磁盘或者硬盘,并且就叫做虚拟内存。
分页就是说,将磁盘或者硬盘分为大小固定的数据块,叫做页,然后内存也分为同样大小的块,叫做页框。当进程执行的时候,会将磁盘的页载入内存的某些页框中,并且正在执行的进程如果发生缺页中断也会发生这个过程。页和页框都是由两个部分组成的,一个是页号或者页框号,一个是偏移量。分页一般是有硬件来完成的,每个页都对应一个页框,它们的对应关系存放在一个叫做页表的数据结构中,页号作为这个页表的索引,页框号作为页表的值。操作系统负责维护这个页表。
在程序运行过程中,如果要访问的页面不在内存中,就发生缺页中断从而将该页调入内存中。此时如果内存已无空闲空间,系统必须从内存中调出一个页面到磁盘对换区中来腾出空间。
最佳算法
所选择的被换出的页面将是最长时间内不再被访问,通常可以保证获得最低的缺页率。这是一种理论上的算法,因为无法知道一个页面多长时间不再被访问。
先进先出
选择换出的页面是最先进入的页面。该算***将那些经常被访问的页面也被换出,从而使缺页率升高。
LRU
虽然无法知道将来要使用的页面情况,但是可以知道过去使用页面的情况。LRU
将最近最久未使用的页面换出。为了实现 LRU,需要在内存中维护一个所有页面的链表。当一个页面被访问时,将这个页面移到链表表头。这样就能保证链表表尾的页面是最近最久未访问的。因为每次访问都需要更新链表,因此这种方式实现的 LRU
代价很高。
时钟算法
时钟算法使用环形链表将页面连接起来,再使用一个指针指向最老的页面。它将整个环形链表的每一个页面做一个标记,如果标记是0
,那么暂时就不会被替换,然后时钟算法遍历整个环,遇到标记为1
的就替换,否则将标记为0
的标记为1
。
Linux
文件系统里面有文件和目录,组成一个树状的结构,树的每一个叶子节点表示文件或者空目录。每个文件基本上都由两部分组成:
inode
:一个文件占用一个 inode
,记录文件的属性,同时记录此文件的内容所在的 block
编号; block
:记录文件的内容,文件太大时,会占用多个 block
。 除此之外还包括:
superblock
:记录文件系统的整体信息,包括 inode
和 block
的总量、使用量、剩余量,以及文件系统的格式与相关信息等; block bitmap
:记录 block
是否被使用的位图。 当要读取一个文件的内容时,先在 inode
中查找文件内容所在的所有 block
,然后把所有 block
的内容读出来。
https://blog.csdn.net/menghefang/article/details/88624161
建立软链接:ln -s 源文件或目录 目标文件或目录
删除软链接:rm –rf 软链接名称
修改软链接:ln –snf 新的源文件或目录 目标文件或目录
硬链接就是在目录下创建一个条目,记录着文件名与 inode
编号,这个 inode
就是源文件的 inode
。删除任意一个条目,文件还是存在,只要引用数量不为 0
。但是硬链接有限制,它不能跨越文件系统,也不能对目录进行链接。
符号链接文件保存着源文件所在的绝对路径,在读取时会定位到源文件上,可以理解为 Windows
的快捷方式。当源文件被删除了,链接文件就打不开了。因为记录的是路径,所以可以为目录建立符号链接。
原文:https://www.cnblogs.com/qmillet/p/13543347.html