操作系统面试题

操作系统基础

什么是操作系统?

1.操作系统(Operating System,简称OS)是管理计算机硬件与软件资源的程序。

2.操作系统本质上是一个运行在计算机上的软件程序,用于管理计算机硬件和软件资源。

3.操作系统存在屏蔽了硬件层的复杂。

4.操作系统的内核(Kernel)是操作系统的核心部分,它负责系统的内存管理,硬件设备的管理,文件系统的管理以及应用程序的管理。内核是连接应用程序和硬件的桥梁,决定着系统的性能和稳定性。

内核态和用户态

在CPU的所有指令中,有些指令是十分危险的,如果错用,将导致系统崩溃,比如清除内存、设置时钟等。如果所有程序都能使用这些指令,那么系统死机的概率将大大增加。所以,CPU将指令分为特权指令和非特权指令,对于危险的指令,只允许操作系统及其相关模块使用,普通应用程序只能使用那些不会造成灾难的指令。

从用户空间到内核空间有以下触发手段:

1.系统调用。用户进程通过系统调用申请使用操作系统提供的服务程序来完成工作。

2.中断。当外围设备完成用户请求后,会向CPU发送中断信号。这时CPU会暂时执行下一条指令(用户态)转而执行该中断信号对应的中断处理程序(内核态)。

3.异常。当CPU在执行运行在用户态下的程序时,发生了某些事先不可预知的异常,这时会触发由当前运行进程切换到处理此异常相关的内核相关程序中,也就转换到了内核态,比如缺页异常。

中断和异常

中断(Interruption)也称外中断,是指来自CPU执行指令外部的事件,通常用于信息输入/输出,如设备发出的I/O结束中断,表示设备输入/输出已经完成。时钟中断,表示一个固定的事件片已到,让处理机处理计时、启动定时运行的任务等。

异常(Exception)也称中断,是指来自CPU执行指令内部的事件,如程序的非法操作码、地址越界、运算溢出、虚存系统的缺页以及专门的陷入指令等引起的事件。异常不能被屏蔽,一旦出现,就应立即处理。故障通常是指由指令执行引起的异常,如非法操作码、缺页故障、除数为运算溢出等。自陷是一种事先安排的“异常”,用于在用户态下调用操作系统内核程序,如条件陷阱指令。终止是指出现了使得CPU无法继续执行的硬件故障,如控制器出错、存储器校验等。

系统调用

根据进程访问资源的特点,我们可以把进程在系统上运行分为两个级别:

1.用户态:用户态运行的进程可以直接读取用户程序的数据。

2.系统态:可以简单的理解系统运行的进程和程序几乎可以访问计算机的任何资源,不受限制。

系统调用按功能大致可以分为下面几类:

1.设备管理:完成设备的请求或释放,以及设备启动等功能。

2.文件管理:完成文件的读、写、创建及删除等功能。

3.进程控制:完成进程的创建、撤销、阻塞及唤醒等功能。

4.进程通信:完成进程之间的消息传递或信号传递等功能

5.内存管理:完成内存的分配、回收以及获取作业占用内存区大小及地址。

进程和线程

(1)一个线程从属于一个进程;一个进程可以包含多个线程。
(2)进程是系统资源调度的最小单位;线程是CPU调度的最小单位。
(3)进程系统开销显著大于线程开销;线程需要的系统资源更少。
(4)进程在执行时拥有独立的内存单元,多个线程共享进程的内存,如代码段、数据段、扩展段;但每个线程拥有自己的栈段和寄存器组。
(5)进程切换时需要刷新TLB并获取新的地址空间,然后切换硬件上下文和内核栈,线程切换时只需要切换硬件上下文和内核栈。
(6)通信方式不一样。
(7)进程适应于多核、多机分布;线程适用于多核

进程间的通信方式

1.管道/匿名管道(Pipes):用于具有亲缘关系的父子进程或者兄弟进程之间的通信。

2.消息队列(Message):类似于链表的结构存储信息,存放在内存中并有消息队列标识符标识;它相比于管道,不止能传输字节流,也没有缓冲区大小的限制;消息队列允许一个或多个进程向它写入与读取消息;它实现了消息的随机读取;管道和消息队列的通信数据都是先进先出的原则。

3.内存共享(Shared memory):使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种方式需要依赖某种同步操作,如互斥锁和信号量等。共享内存的整个通信过程对消息的复制只有两次 用户空间 到 内存 到 用户空间;管道,消息队列则需要四次  用户空间缓冲区 到 内核空间缓存区 到 内存中 内核空间缓冲区 到 用户空间缓存区。

4.信号(Signal):信号是进程通信机制中唯一的异步通知机制。

5.信号量(Semaphores):信号量是一个计数器,用于多进程对共享数据的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程不同线程之间的同步手段。PV操作

6.套接字(Sockets):此方法主要用于在客户端和服务器之间通过网络进行通信。套接字是支持TCP/IP的网络通信的基本操作单元,可以看作是不同主机之间的进程进行双向通信的端点。简单的说就是通信双方的一种约定,用套接字中的相关函数完成通信过程。套接字也是一种进程间通信机制,与其他机制不同的是,它可以用于不同机器之间的进程通信(套接字=IP地址+端口号)。

协程

协程:协程是微线程,在子程序内部执行,可在子程序内部中断,转而执行别的子程序,在适当的时候再返回回来接着执行。

线程与协程的区别:

(1)协程执行效率高。协程直接操作栈基本没有内核栈切换的开销,所以上下文的切换非常快,切换的开销比线程更小。

(2)协程不需要多线程的锁机制,因为多个协程从属于一个线程,不存在同时写变量冲突,效率比线程高。

(3)一个线程可以有多个协程

 

为什么协程比线程切换的开销小?

(1)协程执行效率高。协程直接操作栈基本没有内核栈切换的开销,所以上下文的切换非常快,切换开销比线程更小。

(2)协程不需要多线程锁机制,因为多个协程从属于一个线程,不存在同时写变量冲突,效率比线程高。避免了加锁解锁的开销。

进程

进程切换为什么比线程更消耗资源

进程切换时需要刷新TLB并获取新的地址空间,然后切换硬件上下文和内核栈;线程切换时只需要切换硬件上下文和内核栈。
 
进程是程序的动态表现。 一个程序进行起来后,会使用很多资源,比如使用寄存器,内存,文件等。每当切换进程时,必须要考虑保存当前进程的状态。状态包括存放在内存中的程序的代码和数据,它的栈、通用目的寄存器的内容、程序计数器、环境变量以及打开的文件描述符的集合,这个状态叫做上下文(Context)。可见,想要切换进程,保存的状态还不少。不仅如此,由于虚拟内存机制,进程切换时需要刷新TLB并获取新的地址空间。线程存在于进程中,一个进程可以有一个或多个线程。线程是运行在进程上下文中的逻辑流,这个线程可以独立完成一项任务。同样线程有自己的上下文,包括唯一的整数线程ID, 栈、栈指针、程序计数器、通用目的寄存器和条件码。可以理解为线程上下文是进程上下文的子集。由于保存线程的上下文明显比进程的上下文小,因此系统切换线程时,必然开销更小.
 

僵尸进程和孤儿进程

我们知道在unix/linux中,正常情况下,子进程是通过父进程创建的,子进程再创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程到底什么时候结束。 当一个进程完成它的工作终止之后,它的父进程需要调用wait()或者waitpid()系统调用取得子进程的终止状态。
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵尸进程。
 

进程之间共享内存的通信方式有什么好处?

采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的缓存。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只需拷贝两次;一次从输入文件到共享内存区,另一次从共享内存区到输出文件。

进程的调度算法有哪些?

①先来先去服务
先来先去服务调度算法是一种最简单的调度算法,也称为先进先出或严格排队方案。当每个进程就绪后,它加入就绪队列。当前正运行的进程停止执行,选择在就绪队列中存在时间最长的进程运行。该算法既可以用于作业调度,也可以用于进程调度。先来先去服务比较适合于长作业(进程),而不利于短作业(进程)。
②时间片轮转法
轮转法是基于适中的抢占策略的,以一个周期性间隔产生时钟中断,当中断发生后,当前正在运行的进程被置于就绪队列中,然后基于先来先去服务策略选择下一个就绪作业的运行。这种技术也称为时间片,因为每个进程在被抢占之前都给定一片时间。
③最短进程优先
最短进程优先是一个非抢占策略,他的原则是下一次选择预计处理时间最短的进程,因此短进程将会越过长作业,跳至队列头。该算法即可用于作业调度,也可用于进程调度。但是他对长作业不利,不能保证紧迫性作业(进程)被及时处理,作业的长短只是被估算出来的。
④最短剩余时间优先
最短剩余时间是针对最短进程优先增加了抢占机制的版本。在这种情况下,进程调度总是选择预期剩余时间最短的进程。当一个进程加入到就绪队列时,他可能比当前运行的进程具有更短的剩余时间,因此只要新进程就绪,调度程序就能可能抢占当前正在运行的进程。像最短进程优先一样,调度程序正在执行选择函数是必须有关于处理时间的估计,并且存在长进程饥饿的危险。
⑤最高响应比优先
根据比率:R=(w+s)/s (R为响应比,w为等待处理的时间,s为预计的服务时间)如果该进程被立即调用,则R值等于归一化周转时间(周转时间和服务时间的比率)。R最小值为1.0,只有第一个进入系统的进程才能达到该值。调度规则为:当前进程完成或被阻塞时,选择R值最大的就绪进程,它说明了进程的年龄。当偏向短作业时,长进程由于得不到服务,等待时间不断增加,从而增加比值,最终在竞争中赢了短进程。和最短进程优先、最短剩余时间优先一样,使用最高响应比策略需要估计预计服务时间。
⑥反馈法
如果没有关于进程相对长度的任何信息,则最短进程优先,最短剩余时间、最高响应优先比都不能使用。另一种导致偏向短作业的方法是处罚运行时间较长的作业,换句话说,如果不能获得剩余的执行时间,那就关注已执行了的时间。
方法为:调度基于被抢占原则(按时间片)并使用动态优先级机制。当一个进程第一次进入系统中时,他被放置在一个优先级队列中,当第一次被抢占后并返回就绪状态时,它被放置在下一个低优先级队列中,在随后的时间里,每当被抢占时,他被降级到下一个低优先级队列中。一个短进程很快被执行完,不会在就绪队列中降很多级,一个长进程会逐渐降级。因此先到的进程和短进程优先于长进程和老进程。在每个队列中,除了优先级在最低的队列中之外,都是用简单的先来先去服务机制,一旦一个进程处于优先级最低的队列中,它就不可能在降级,但会重复的返回该队列,直到运行结束。因此,该队列可按照轮转方式调度。
⑦多级反馈队列调度算法
多级反馈队列算法,不必事先知道各种进程所需要执行的时间,他是当前被公认的一种较好的进程调度算法。其实
施过程如下:
1)设置多个就绪队列,并为各个队列赋予不同的优先级。在优先权越高的队列中,为每个进程所规定的执行时间片就越小。
2)当一个新进程进入内存后,首先放入第一队列的末尾,按照先来先去原则排队等候调度。如果他能在一个时间片中完成,便可撤离;如果未完成,就转入第二队列的末尾,同样等待调度.....如此下去,当一个长作业(进程)从第一队列依次将到第n队列(最后队列)后,便按第n队列时间片轮转运行。
3)仅当第一队列空闲的时候,调度程序才调度第二队列中的进程运行;仅当第1到(i-1)队列空时,才会调度第i队列中的进程运行,并执行相应的时间片轮转。
4)如果处理机正在处理第i队列中某进程,又有新进程进入优先权较高的队列,则此新队列抢占正在运行的处理机,并把正在运行的进程放在第i队列的队尾。

 IO多路复用

IO 多路复用是一种同步 IO 模型,实现一个线程可以监视多个文件句柄。一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪时会阻塞应用程序,交出 cpu。IO 是指网络 IO,多路指多个TCP连接(即 socket 或者 channel),复用指复用一个或几个线程。
意思说一个或一组线程处理多个 TCP 连接。最大优势是减少系统开销小,不必创建过多的进程/线程,也不必维护这些进程/线程。IO 多路复用的三种实现方式:select、poll、epoll。

乐观锁与悲观锁

一个共享数据加了悲观锁,那线程每次想操作这个数据前都会假设其他线程也可能会操作这个数据,所以每次操作前都会上锁,这样其他线程想操作这个数据拿不到锁只能阻塞了。

 

 

 在 Java 语言中 synchronized 和 ReentrantLock等就是典型的悲观锁,还有一些使用了 synchronized 关键字的容器类如 HashTable 等也是悲观锁的应用。

 

 

乐观锁操作数据时不会上锁,在更新的时候会判断一下在此期间是否有其他线程去更新这个数据。

 

 

 乐观锁可以使用版本号机制CAS算法实现。在 Java 语言中 java.util.concurrent.atomic包下的原子类就是使用CAS 乐观锁实现的。

CAS算法
即compare and swap(比较与交换),是一种有名的无锁算法。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。CAS算法涉及到三个操作数
○ 需要读写的内存值 V
○ 进行比较的值 A
○ 拟写入的新值 B

独占锁和共享锁

独占锁:是指锁一次只能被一个线程所持有。如果一个线程对数据加上排他锁后,那么其他线程不能再对该数据加任何类型的锁。获得独占锁的线程即能读数据又能修改数据。

JDK中的synchronizedjava.util.concurrent(JUC)包中Lock的实现类就是独占锁。

 

共享锁:是指锁可被多个线程所持有。如果一个线程对数据加上共享锁后,那么其他线程只能对数据再加共享锁,不能加独占锁。获得共享锁的线程只能读数据,不能修改数据。

在 JDK 中 ReentrantReadWriteLock 就是一种共享锁。

互斥锁和读写锁

互斥锁是独占锁的一种常规实现,是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。

 

 

 互斥锁一次只能一个线程拥有互斥锁,其他线程只有等待。

 

读写锁是共享锁的一种具体实现。读写锁管理一组锁,一个是只读的锁,一个是写锁。

读锁可以在没有写锁的时候被多个线程同时持有,而写锁是独占的。写锁的优先级要高于读锁,一个获得了读锁的线程必须能看到前一个释放的写锁所更新的内容。

读写锁相比于互斥锁并发程度更高,每次只有一个写线程,但是同时可以有多个线程并发读。

 

 

公平锁与非公平锁

公平锁是指多个线程按照申请锁的顺序来获取锁,这里类似排队买票,先来的人先买,后来的人在队尾排着,这是公平的。

非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁,在高并发环境下,有可能造成优先级翻转,或者饥饿的状态(某个线程一直得不到锁)。

 

可重入锁

可重入锁又称之为递归锁,是指同一个线程在外层方法获取了锁,在进入内层方法会自动获取锁。

 

 

对于Java ReentrantLock而言, 他的名字就可以看出是一个可重入锁。对于Synchronized而言,也是一个可重入锁。

敲黑板:可重入锁的一个好处是可一定程度避免死锁。

自旋锁

自旋锁是指线程在没有获得锁时不是被直接挂起,而是执行一个忙循环,这个忙循环就是所谓的自旋。

 

 

自旋锁的目的是为了减少线程被挂起的几率,因为线程的挂起和唤醒也都是耗资源的操作。

如果锁被另一个线程占用的时间比较长,即使自旋了之后当前线程还是会被挂起,忙循环就会变成浪费系统资源的操作,反而降低了整体性能。因此自旋锁是不适应锁占用时间长的并发情况的。

分段锁

分段锁 是一种锁的设计,并不是具体的一种锁。

分段锁设计目的是将锁的粒度进一步细化,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。

 

 在 Java 语言中 CurrentHashMap 底层就用了分段锁,使用Segment,就可以进行并发使用了。

锁升级

JDK1.6 为了提升性能减少获得锁和释放锁所带来的消耗,引入了4种锁的状态:无锁、偏向锁、轻量级锁和重量级锁,它会随着多线程的竞争情况逐渐升级,但不能降级。

无锁

无锁状态其实就是上面讲的乐观锁,这里不再赘述。

偏向锁

Java偏向锁(Biased Locking)是指它会偏向于第一个访问锁的线程,如果在运行过程中,只有一个线程访问加锁的资源,不存在多线程竞争的情况,那么线程是不需要重复获取锁的,这种情况下,就会给线程加一个偏向锁。

偏向锁的实现是通过控制对象Mark Word的标志位来实现的,如果当前是可偏向状态,需要进一步判断对象头存储的线程 ID 是否与当前线程 ID 一致,如果一致直接进入。

轻量级锁

当线程竞争变得比较激烈时,偏向锁就会升级为轻量级锁,轻量级锁认为虽然竞争是存在的,但是理想情况下竞争的程度很低,通过自旋方式等待上一个线程释放锁。

重量级锁

如果线程并发进一步加剧,线程的自旋超过了一定次数,或者一个线程持有锁,一个线程在自旋,又来了第三个线程访问时(反正就是竞争继续加大了),轻量级锁就会膨胀为重量级锁,重量级锁会使除了此时拥有锁的线程以外的线程都阻塞。

升级到重量级锁其实就是互斥锁了,一个线程拿到锁,其余线程都会处于阻塞等待状态。

在 Java 中,synchronized 关键字内部实现原理就是锁升级的过程:无锁 --> 偏向锁 --> 轻量级锁 --> 重量级锁。。


锁粗化就是将多个同步块的数量减少,并将单个同步块的作用范围扩大,本质上就是将多次上锁、解锁的请求合并为一次同步请求。

锁消除是指虚拟机编译器在运行时检测到了共享数据没有竞争的锁,从而将这些锁进行消除。

什么情况下会产生死锁?

如果在计算机系统中同时具备下面四个必要条件时,那么会发生死锁。换句话说,只要下面四个条件有一个不具备,系统就不会出现死锁。
互斥条件。即某个资源在一段时间内只能由一个进程占有,不能同时被两个或两个以上的进程占有。这种独占资源如CD-ROM驱动器,打印机等等,必须在占有该资源的进程主动释放它之后,其它进程才能占有该资源。这是由资源本身的属性所决定的。如独木桥就是一种独占资源,两方的人不能同时过桥。
不剥夺条件。进程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放。如过独木桥的人不能强迫对方后退,也不能非法地将对方推下桥,必须是桥上的人自己过桥后空出桥面(即主动释放占有资源),对方的人才能过桥。
请求和保持条件。进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞;但是,它在等待新资源之时,仍继续占用已占有的资源。还以过独木桥为例,甲乙两人在桥上相遇。甲走过一段桥面(即占有了一些资源),还需要走其余的桥面(申请新的资源),但那部分桥面被乙占有(乙走过一段桥面)。甲过不去,前进不能,又不后退;乙也处于同样的状况。
循环等待条件。存在一个进程等待序列{P1,P2,...,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一源,......,而Pn等待P1所占有的的某一资源,形成一个进程循环等待环。就像前面的过独木桥问题,甲等待乙占有的桥面,而乙又等待甲占有的桥面,从而彼此循环等待。
上面提到的这四个条件在死锁时会同时发生。也就是说,只要有一个必要条件不满足,则死锁就可以排除。
 

死锁处理策略

(1)死锁预防。设置某些限制条件,破坏产生死锁的4个必要条件之一或几个。

(2)死锁避免。死锁避免同样属于事先预防策略,但并不是事先采取某种限制措施破坏死锁的必要条件,而是在资源动态分配过程中,防止系统进入不安全状态,以避免发生死锁。这种方法所施加的限制较弱,可以获得较好的系统性能。1.系统安全状态,允许进程动态地申请资源,但系统在进行资源分配前,应先计算此次分配的安全性。若此次分配不会导致系统进入不安全状态,则允许分配;否则等待。2.银行家算法,进程运行前先声明对各种资源的最大需求量,当进程在执行中继续申请资源时,先测试该进程已占用的资源数与本次申请的资源数之和是否超过进程声明的最大需求量。已经拥有的+需要的 <= 还剩可分配的

(3)死锁的检测以及解除。无须采取任何限制性措施,允许进程在运行过程中发生死锁。通过系统的检测机构以及及时检测出死锁的发生,然后采取某种措施解除死锁。

死锁与饥饿的区别

1.进入饥饿状态的进程可以只有一个,而因循环等待条件而进入死锁状态的进程至少有2个

2.发生饥饿的进程的状态可能是就绪态(长期得不到处理机),也可能是阻塞态(长期得不到IO设备),而发生死锁的进程的状态则必定是阻塞态。

操作系统的地址有几种

物理地址:

在存储器里以字节为单位存储信息,为正确地存放或取得信息,每一个字节单位给唯一一个的存储器地址,成为物理地址,又称为实际地址或绝对地址。

地址从0开始编号,顺序地每次加1,因此存储器的物理地址空间是呈线性增长的。它是用二进制数来表示的,是无符号整数,书写格式为十六进制数。它是出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果。用于内存芯片级的单元寻址,与处理器和CPU连接的地址总线相对应。
逻辑地址:
逻辑地址是指在计算机体系结构中是指应用程序角度看到的内存单元、存储单元、网络主机的地址。逻辑地址往往不同于物理地址,通过地址翻译器或映射函数可以把逻辑地址转换为物理地址。
在有地址变换功能的计算机中,访问指令给出的地址 (操作数) 叫逻辑地址,也叫相对地址。要经过寻址方式的计算或变换才得到内存储器中的物理地址。把用户程序中使用的地址称为相对地址即逻辑地址。逻辑地址由两个16位的地址分量构成,一个为段基值,另一个为偏移量。两个分量均为无符号数编码。
虚拟地址(线性地址):
线性地址是逻辑地址到物理地址变换之间的中间层。在分段部件中逻辑地址是段中的偏移地址,然后加上基地址就是虚拟地址。
线性地址是一个32位无符号整数,可以用来表示高达4GB的地址,也就是,高达4294967296个内存单元。线性地址通常用十六进制数字表示,值的范围从0x00000000到0xffffffff)。程序代码会产生逻辑地址,通过逻辑地址变换就可以生成一个线性地址。如果启用了分页机制,那么线性地址可以再经过变换以产生一个物理地址。当采用4KB分页大小的时候,线性地址的高10位为页目录项在页目录表中的编号,中间10位为页表中的页号,其低12位则为偏移地址。如果是使用4MB分页机制,则高10位页号,低22位为偏移地址。如果没有启用分页机制,那么线性地址直接
就是物理地址。
 

缓存溢出

缓存溢出是指输入到一个缓冲区或者数据保存区域的数据量超过了其容量,从而导致覆盖了其他区域数据的情况。

攻击者造成并利用这种情况使系统崩溃或者通过特质的代码来控制系统。

被覆盖的区域可能存在其他程序的变量、参数、类似于返回地址或指向前一个栈帧的指针等程序控制流数据,缓冲区可以位于堆、栈或者进程的数据段。

这种错误可能产生如下后果:
1)破坏程序的数据;
2)改变程序的控制流,因此可能访问特权代码。
最终很有可能造成程序终止。当攻击者成功地攻击了一个系统之后,作为攻击的一部分,程序的控制流可能会跳转到攻击者选择的代码处,造成的结果是被攻击的进程可以执行任意的特权代码(比如通过判断输入是否和密码匹配来访问特权代码,如果存在缓冲区漏洞,非法输入导致存放“密码”的内存区被覆盖,从而使得“密码”被改写,因此判断为匹配进而获得了特权代码的访问权)
缓冲区溢出攻击是最普遍和最具危害性的计算机安全攻击类型之一。
如何预防缓存溢出
广义上分为两类:
(1)编译时防御系统,目的是强化系统以抵御潜伏于新程序中的恶意攻击;
(2)运行时预防系统,目的是检测并终止现有程序中的恶意攻击。
 

内存和缓存的区别

内存和缓存时计算机不同的组成部件。

内存:内存也被称为内存储器,其作用时用于暂时存放CPU的运算数据,以及与硬盘等外部存储交换的数据。只要计算机在运行中,CPU就会把需要进行运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来,内存的运行也决定了计算机的稳定运行。

缓存:CPU芯片面积和成本的因素影响,决定了缓存都很小。现在一般的缓存不过几M,CPU缓存的运行频率极高,一般是和处理器同频运作,工作效率远远大于系统内存和硬盘。实际工作时,CPU往往需要重复读取同样的数据块,而缓存容量的增大,可以大幅提升CPU内部读取数据的命中频率,而不用再到内存或者硬盘上寻找,以此提高系统性能。

硬链接和软链接

区别:

(1)软连接可以为文件和目录创建链接;硬链接只能为文件创建链接;

(2)软连接可以跨文件系统;硬链接必须是同一个文件系统

(3)硬链接因为只是文件的一个别名,所以不重复占用内存;软链接因为只是一个访问文件的快捷方式文件,文件只包含快捷指向信息,所以占用内存很小;

(4)软链接的文件权限和源文件可以不一样;硬链接文件权限是一样的,因为他们本来就是一个文件的不同名称而已。

二者使用场景
一般比较重要的文件我们担心文件被误删除且传统复制备份方式占用double数量的空间会造成浪费,可以使用硬链做备份来解决;软链接一般被用来设置可执行文件的快捷方式的路径。
硬链接和软链接区别:
1.不同点:源文件删除,硬链接的文件不受影响,软链接文件失效
2.相同点:源文件更改,硬链接的文件和软链接的文件同时变化

 

posted @ 2022-12-19 09:20  白非立  阅读(351)  评论(0)    收藏  举报