后端知识点链接(二):操作系统、Linux

操作系统

  • 2.5w字 + 36 张图爆肝操作系统面试题,太牛逼了!

  • 32位系统和64位系统有什么区别++中32位和64位有什么区别同花顺提前批) 计算机基础—-32位操作系统和64位操作系统的区别、C++那些细节–32位64位数据类型的区别
    1)支持的内存不同
    a、32位:最多支持4G的内存
    b、64位:支持4G 8G 16G 32G 64G 128G 256G内存,理论上可以无限支持,只要主板上有足够的内存条
    2)支持的处理器和软件不同
    a、32位:能完全支持64位的处理,支持基于32位的软件,不能运行64位的软件
    b、64位:支持基于64位的处理器,两种类型软件都支持
    3)C++数据类型大小不同
    a、32位:指针大小为4byte,可以表示2^32,string类型为28byte
    b、64位:指针大小为8byte,可以表示2^64,string类型为32byte,相差了一个指向字符串开头的指针

  • 虚拟内存 20 张图揭开「内存管理」的迷雾,瞬间豁然开朗
    1)虚拟内存的作用/strong>
    a、虚拟内存:我们程序所使用的内存地址叫做虚拟内存地址(Virtual Memory Address)
    b、物理内存:实际存在硬件里面的空间地址叫物理内存地址(Physical Memory Address)
    c、机制和作用:操作系统引入了虚拟内存,进程持有的虚拟地址会通过 CPU 芯片中的内存管理单元(MMU)的映射关系,来转换变成物理地址,然后再通过物理地址访问内存,这样不同进程访问地址不会冲突。
    2)页表在哪里/strong>
    页表实际上存储在 CPU 的内存管理单元 (MMU)
    3)如何判断逻辑地址是否已经映射在物理地址上/strong>
    无缺页中断

  • 缺页中断何时发生详解缺页中断—–缺页中断处理(内核、用户)
    1)编码错误:当内存管理单元(MMU)中确实没有创建虚拟物理页映射关系,并且在该虚拟地址之后再没有当前进程的线性区(vma)的时候,可以肯定这是一个编码错误,这将杀掉该进程。
    2)缺页中断:当MMU中确实没有创建虚拟页物理页映射关系,并且在该虚拟地址之后存在当前进程的线性区vma的时候,这很可能是缺页中断,并且可能是栈溢出导致的缺页中断。
    3)内存调用:当使用malloc或mmap等希望访问物理空间的库函数或系统调用后,由于linux并未真正给新创建的vma映射物理页,此时若先进行写操作,将产生缺页中断;若先进行读操作,将被映射给默认的零页,等再进行写操作时,仍会产生缺页中断,这次必须分配1物理页了,进入写时复制的流程。
    4)Fork函数:当使用fork等系统调用创建子进程时,子进程不论有无自己的vma,它的vma都有对于物理页的映射,但它们共同映射的这些物理页属性为只读,即linux并未给子进程真正分配物理页,当父子进程任何一方要写相应物理页时,导致缺页中断的写时复制。

  • 缺页中断处理流程缺页中断处理过程、操作系统—(35)缺页中断与缺页中断处理过程
    1)保存现场:首先硬件会陷入内核,在堆栈中保存程序计数器,将当前指令的信息保存在CPU特殊的寄存器
    2)查找虚拟页面:当操作系统发现是一个页面中断时,查找出来发生页面中断的虚拟页面(进程地址空间中的页面)。这个虚拟页面的信息通常会保存在一个硬件寄存器中,如果没有的话,操作系统必须检索程序计数器
    3)查找空闲页框:操作系统查找一个空闲的页框(物理内存页面),如果没有则通过页面置换算法找到空闲页框,此时将页框置为忙状态,以防页框被其它进程抢占掉,如果找的页框中的内容被修改了,则需要将修改的内容保存到磁盘上,此时会引起一个写磁盘调用,发生上下文切换(在等待磁盘写的过程中让其它进程运行)
    4)复制磁盘内容:页框干净后,操作系统根据虚拟地址对应磁盘上的位置,将磁盘上的页面内容复制到空闲页框中,此时会引起一个读磁盘调用,发生上下文切换,当磁盘页面内容全部装入页框后,向操作系统发送一个中断。操作系统更新页表项,将虚拟页面映射的页框号更新为写入的页框,并将页框标记为正常状态
    5)恢复现场:恢复缺页中断发生前的状态,将程序指令器重新指向引起缺页中断的指令,调度引起页面中断的进程,操作系统返回汇编代码例程,汇编代码例程恢复现场,将之前保存在通用寄存器中的信息恢复。

  • 虚拟内存页面置换算法 【操作系统 – 5】虚拟内存页面置换算法
    1)先进先出页面置换算法(FIFO)
    a、定义:该算法总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面予以淘汰。
    b、实现:只需把页面按先后次序链接成一个队列,并设置一个替换指针,使它总是指向最老的页面。
    c、抖动现象(Belady):采用FIFO算法时,如果对一个进程未分配它所要求的全部页面,有时就会出现分配的页面数增多,缺页率反而提高的异常现象。该算法与进程实际运行的规律不相适应,
    d、原因:因为在进程中,有些页面经常被访问,比如,含有全局变量、常用函数、例程等的页面,FIFO算法并不能保证这些页面不被淘汰。
    2)最佳置换算法(Optimal)
    a、定义:其所选择的被淘汰页面,将是以后永不使用的,或是在最长(未来)时间内不再被访问的页面。采用最佳置换算法,通常可保证获得最低的缺页率。
    b、缺点:目前还无法预知一个进程在内存的若干个页面中,哪一个页面是未来最长时间内不再被访问的,因而该算法是无法实现的,但可以利用该算法去评价其它算法。
    3)最近最久未使用置换算法(LRU)
    LRU置换算法是选择最近最久未使用的页面淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问所经历的时间t,当须淘汰一个页面时,选择现有页面中其t值最大的,即最近最久未使用的页面淘汰。
    4)最少使用置换算法(LFU)
    在采用最少使用置换算法时,应为在内存中的每个页面设置一个移位寄存器,用来记录该页面被访问的频率。该置换算法选择在之前时期使用最少的页面作为淘汰页。

  • 引起上下文切换的原因有哪些存器、上下文、栈 基本功:线程上下文切换、线程切换是如何给 CPU 洗脑的br> 1)上下文切换类别
    a、进程切换,两个进程之间的切换
    b、线程切换,同一进程中的两个线程之间的切换
    c、模式切换,在给定线程中,用户模式和内核模式的切换
    d、地址空间切换,将虚拟内存切换到物理内存
    2)上下文切换原因
    a、时间片用完:当前执行任务(线程)的时间片用完之后,系统CPU正常调度下一个任务
    b、中断处理:其他程序”打断”了当前正在运行的程序。当CPU接收到中断请求时,会在正在运行的程序和发起中断请求的程序之间进行一次上下文切换。中断分为硬件中断和软件中断,软件中断包括因为IO阻塞、未抢到资源或者用户代码等原因,线程被挂起。
    c、用户态切换:对于一些操作系统,当进行用户态切换时也会进行一次上下文切换,虽然这不是必须的。
    d、多进程或多线程切换:多个任务抢占锁资源,在多任务处理中,CPU会在不同程序之间来回切换,每个程序都有相应的处理时间片,CPU在两个时间片的间隔中进行上下文切换
    3)解决方法
    a、无锁并发编程:多线程处理数据时,可以用一些办法来避免使用锁,如将数据的ID按照Hash取模分段,不同的线程处理不同段的数据
    b、CAS算法:Java的Atomic包使用CAS算法来更新数据,而不需要加锁
    c、使用最少线程或进程
    d、协程:单线程里实现多任务的调度,并在单线程里维持多个任务间的切换

  • 进程切换与线程切换的区别什么虚拟地址切换很慢送命题:进程切换与线程切换的区别br> 1)进程切换和线程切换的区别
    进程切换与线程切换的一个最主要区别就在于进程切换涉及到虚拟地址空间的切换而线程切换则不会。因为每个进程都有自己的虚拟地址空间,而线程是共享所在进程的虚拟地址空间的,因此同一个进程中的线程进行线程切换时不涉及虚拟地址空间的转换。
    2)为什么虚拟地址切换很慢/strong>
    页表切换、页表查找慢、TLB失效
    现在我们已经知道了进程都有自己的虚拟地址空间,把虚拟地址转换为物理地址需要查找页表,页表查找是一个很慢的过程,因此通常使用Cache来缓存常用的地址映射,这样可以加速页表查找,这个cache就是TLB,Translation Lookaside Buffer,我们不需要关心这个名字只需要知道TLB本质上就是一个cache,是用来加速页表查找的。由于每个进程都有自己的虚拟地址空间,那么显然每个进程都有自己的页表,那么当进程切换后页表也要进行切换,页表切换后TLB就失效了,cache失效导致命中率降低,那么虚拟地址转换为物理地址就会变慢,表现出来的就是程序运行会变慢,而线程切换则不会导致TLB失效,因为线程线程无需切换地址空间,因此我们通常说线程切换要比较进程切换块,原因就在这里。

  • 了解协程吗程上下文切换实现个连接分配一个协程,开销会不会很大是每个连接分配一个内核级线程,可不可以核级线程切换的开销linux进程-线程-协程上下文环境的切换与实现、协程是什么么来的有什么作用协程不过是用户态的线程,这句话对吗C语言实现协程(一)
    协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。
    协程适合io密集型场景,处理完一个io立即切换,不用涉及用户态和内核态的切换,不适合计算密集型场景,一个协程处理过久导致其他协程等待过久。

  • 用户态和内核态的区别线程-用户态(也有叫协程的)和内核态的区别
    1)由于需要限制不同的程序之间的访问能力, 防止他们获取别的程序的内存数据, 或者获取外围设备的数据, 并发送到网络, CPU划分出两个权限等级 :用户态和内核态
    2)用户态:只能受限的访问内存, 且不允许访问外围设备. 占用CPU的能力被剥夺, CPU资源可以被其他程序获取
    3)内核态:CPU可以访问内存所有数据, 包括外围设备, 例如硬盘, 网卡. CPU也可以将自己从一个程序切换到另一个程序

  • 用户态和内核态怎么切换入内核态的方式有哪些操作系统用户态和内核态之间的切换过程
    1)系统调用
    这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作,比如前例中fork()实际上就是执行了一个创建新进程的系统调用。
    2)异常
    当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常
    3)外设中断
    当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,CPU会去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程发生了由用户态到内核态的切换。

  • 库函数和系统调用的区别库函数和系统调用的区别和联系

    后端知识点链接(二):操作系统、Linux
  • 进程和线程的区别进程、线程和协程之间的区别和联系、PCB与进程分配资源
    1)根本区别
    a、进程:操作系统资源分配的基本单位
    b、线程:CPU处理器任务调度和执行的基本单位
    2)资源开销和内存分配
    a、进程:每个进程都有独立的代码、数据空间(程序上下文)和地址空间,程序之间的切换会有较大的开销
    b、线程:线程可以看做轻量级的进程,同一类线程共享代码、数据空间和地址空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小
    3)影响关系
    a、进程:一个进程崩溃后,在保护模式下不会对其他进程产生影响
    b、线程:一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮
    4)通信机制
    a、进程:通信较复杂,进程之间的通信需要以通信的方式(IPC)进行
    b、线程:通信较方便,同一进程下的线程共享全局变量、静态变量等数据,不过需要处理同步和互斥
    5)执行过程
    a、进程:每个独立的进程有程序运行的入口、顺序执行序列和程序出口。
    b、线程:线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制

  • 线程有什么数据是自己私有,哪些是共享的OS / 线程哪些内容是私有的和共享的br> 1)线程私有
    a、栈(局部变量,函数的参数)。
    b、线程局部存储(Thread Local Storage,TLS),有限的容量。
    c、寄存器 (执行流的基本数据)。
    d、线程ID、信号屏蔽码、信号屏蔽码、错误返回码
    2)线程共享
    a、全局变量、函数里的静态变量。
    b、堆上的数据。
    c、程序代码,任何线程都有权利读取并执行任何代码。
    d、进程打开的文件描述符,A 线程打开的文件可以由 B 线程读写。

  • 进程有哪些状态程的几种状态
    1)运行态:该进程正在执行。
    2)就绪态:进程已经做好了准备,只要有机会就开始执行。
    3)阻塞态(等待态):进程在某些事情发生前不能执行,等待阻塞进程的事件完成。
    4)新建态:刚刚创建的进程,操作系统还没有把它加入到可执行进程组中
    5)退出态:操作系统从可执行进程组中释放出的进程,或由于自身或某种原因停止运行。

  • 哪些情况进程会由运行转为阻塞br> 1)进程缺少相应io资源,阻塞等待资源
    2)访问正在被其他进程访问的临界资源,等待解锁
    3)进程睡眠(sleep)

  • 进程调度算法有哪些操作系统中常用的进程调度算法
    1)先来先服务调度算法
    每次调度都是从后备作业队列中选择一个或多个最先进入该队列的作业,将它们调入内存
    2)短作业(进程)优先调度算法
    进程优先(SPF)调度算法则是从就绪队列中选出一个估计运行时间最短的进程
    3)时间片轮转法
    每次调度时,把CPU分配给队首进程,并令其执行一个时间片。时间片的大小从几ms到几百ms。当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾
    4)多级反馈队列调度算法
    应设置多个就绪队列,并为各个队列赋予不同的优先级,该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小。例如,第二个队列的时间片要比第一个队列的时间片长一倍,第i+1个队列的时间片要比第i个队列的时间片长一倍

  • 进程通信的方式有哪些PC 最快的方式是什么linux基础——linux进程间通信(IPC)机制总结、进程间通信——共享内存(Shared Memory)
    1)匿名管道(PIPE)
    a、定义: 管道实际是用于进程间通信的一段共享内存,一个进程写入数据后,另一进程就可以读取出来
    b、特点:
    ①、管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
    ②、只能用于父子进程或者兄弟进程之间( 具有亲缘关系的进程), 比如fork或exec创建的新进程。
    在使用exec创建新进程时,需要将管道的文件描述符作为参数传递给exec创建的新进程。
    当父进程与使用fork创建的子进程直接通信时,发送数据的进程关闭读端,接受数据的进程关闭写端
    ③、管道对于管道两端的进程而言,就是一个文件,单独构成一种文件系统,并且只存在与内存中
    c、函数:
    创建匿名管道:int pipe(int file_descriptor[2]);
    2)命名管道(FIFO)
    a、定义:命名管道在系统中以文件形式存在,克服了管道的弊端,可以允许没有亲缘关系的进程间通信。
    b、函数:
    创建命名管道:int mkfifo(const char *filename,mode_t mode);
    3)信号 (signal)
    a、定义:信号机制是unix系统中最为古老的进程之间的通信机制,用于一个或几个进程之间传递异步信号。
    b、函数
    ①、截取系统信号:int ret = signal或sigation(SIGSTOP, sig_handle),前一个为信号,后一个为处理函数
    ②、向指定进程发起信号:kill(pid_t pid,int sig)、int raise(int sig)
    ③、指定时间后把SIGALARM发给当前进程:alarm(unsigned int seconds)
    4)消息队列(Message queues)
    a、定义:消息队列是内核地址空间中的内部链表,每个消息队列可以用 IPC标识符唯一地进行识别
    b、对比和优点:
    ①、消息队列克服了信号承载信息量少,管道只能承载无格式字符流
    ②、消息队列也可以独立于发送和接收进程而存在,消除了在同步命名管道的打开和关闭时可能产生的困难
    ③、命名管道中,发送数据用write,接收数据用read,消息队列中,发送数据用msgsnd,接收数据用msgrcv
    ④、发送消息还可以避免命名管道的同步和阻塞问题,不需要由进程自己来提供同步方法
    ⑤、接收程序可以通过消息类型有选择地接收数据,而不是像命名管道中那样,只能默认地接收
    c、函数
    ①、通过目录和ID获取指定IPC标识符:key_t ftok( const char * fname, int id );
    ②、创建和访问一个消息队列:msgget(key_t key,int msgflag);
    ③、把一条消息添加到消息队列中int msgsnd(int msgid,const void *msgptr,size_t msg_sz,int msgflg);
    ④、通过msqid对指定消息队列进行接收操作:msgrcv(int msgid, void *msgptr, size_t msg_sz, long int msgtype, int msgflg);
    5)信号量(Semaphore)
    a、定义:信号量是一种计数器,用于控制对多个进程共享的资源进行的访问。
    ①、创建一个新的信号量集合:int semget(key_t key, int num_sems, int sem_flags);
    ②、改变信号量的值:int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);
    6) 共享内存(Share Memory)
    a、定义:共享内存是在多个进程之间共享内存区域的一种进程间的通信方式
    b、优点:共享内存是 IPC最快捷的方式,因为共享内存方式的通信没有中间过程,多个进程间的共享内存是同一块的物理空间,仅仅映射到各进程的地址不同而已,因此不需要进行复制,可以直接使用此段空间。
    ①、创建一个新的共享内存段:int shmget(key_t key,size_t size,int shmflg);
    ②、将共享内存连接到进程的地址空间中:shmat(int shm_id,const void *shm_addr,int shmflg);
    ③、将共享内存从当前进程中分离:int shmdt(const void *shm_addr);
    7)内存映射(Memory Map)
    a、定义:内存映射文件,是由一个文件到一块内存的映射,只要有一个进程对这块映射文件的内存进行操作,其他进程也能够马上看到,共享内存是内存映射文件的一种特殊情况,内存映射一块内存,而非磁盘文件。
    b、优点:使用内存映射文件不仅可以实现多个进程间的通信,还可以用于处理大文件提高效率。普通的做法是将数据拷贝到缓冲区再拷贝到磁盘文件,一共四次拷贝,如果文件数据量很大,拷贝的开销是非常大的。
    c、函数
    将一个文件或者其它对象映射进内存:void mmap(voidstart,size_t length,int prot,int flags,int fd,off_t offset);
    8)套接字(Socket)
    a、定义:套接字机制不但可以单机的不同进程通信,而且使得跨网机器间进程可以通信
    b、函数
    int bind(int socket,const struct sockaddr *address,size_t address_len);
    int listen(int socket,int backlog);
    int accept(int socket,struct sockaddr *address,size_t *address_len);
    int connect(int socket,const struct sockaddr *addrsss,size_t address_len);

  • 信号的底层原理中断 操作系统中信号工作的底层原理分析
    软中断信号 (简称为信号) 是用来通知进程发生了异步事件,是在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。

  • 进程的同步与互斥方式inux下进程、线程同步几种方法
    1)信号量
    可以借助Linux的信号量的PV操作来实现对临界资源的互斥访问。
    2)文件锁
    linux下可以使用flock()函数对文件进行加锁解锁等操作
    3)无锁CAS访问
    CAS是一组原语指令,用来实现多进/线程下的变量同步。
    CAS原语有三个参数,内存地址,期望值,新值。如果内存地址的值==期望值,表示该值未修改,此时可以修改成新值。否则表示修改失败,返回false,由用户决定后续操作。
    4)校验方式(CRC32校验)
    可以用crc32校验的方式,把变量a的crc32值记录下来,存入另外的变量b。
    在写入变量a的时候,更新完变量a后,再计算出a的crc32值,更新变量b;
    在读取变量a的时候,把读出的值a的crc32值和另外的变量b进行比较,如果不相同,就说明变量a正在更新中,从而实现对该变量的无锁互斥访问。

  • 线程的同步与互斥方式线程的锁了解哪些旋锁和互斥锁的区别用场景多线程的同步与互斥(互斥锁、条件变量、读写锁、自旋锁、信号量)、在Linux中使用线程、自旋锁与互斥锁的区别
    1)互斥锁
    a、定义:互斥锁是一种简单的加锁的方法来控制对共享资源的访问,互斥锁只有两种状态,即上锁和解锁
    b、函数:
    初始化锁:pthread_mutex_init、销毁锁:pthread_mutex_destroy
    上锁:pthread_mutex_lock、解锁:pthread_mutex_unlock
    2)条件变量
    a、定义:条件变量用来自动阻塞一个线程,直到某特殊情况发生,通常条件变量和互斥锁同时使用,线程必须首先锁住互斥量,如果一个条件为假,一个线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程,重新获得互斥锁,重新评价条件
    b、函数:
    初始化条件变量:pthread_cond_init、销毁条件变量:pthread_cond_destroy
    阻塞等待:pthread_cond_wait、唤醒条件变量:pthread_cond_signal
    3)读写锁
    a、定义一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁
    b、状态:读写锁可以有3种状态:读模式下加锁状态、写模式加锁状态、不加锁状态
    c、规则:
    如果有其它线程读数据,则允许其它线程执行读操作,但不允许写操作;
    如果有其它线程写数据,则其它线程都不允许读、写操作。
    d、适用场景:读写锁适合于对数据结构的读次数比写次数多得多的情况。
    e、函数:
    初始化锁:pthread_rwlock_init、销毁锁:pthread_rwlock_destroy
    申请读锁:pthread_rwlock_rdlock、申请写锁:pthread_rwlock_wrlock、解锁:pthread_rwlock_unlock
    4)自旋锁
    a、定义:与互斥量功能一样,互斥量阻塞后休眠让出cpu,而自旋锁阻塞后不会让出cpu,会一直忙等待
    b、适用场景:内核使用的比较多,锁的持有时间比较短,或者说小于2次上下文切换的时间。
    c、函数:
    初始化锁:pthread_spin_init、销毁锁:pthread_spin_destroy
    上锁:pthread_spin_lock、解锁:pthread_spin_unlock
    5)信号量
    a、定义:信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。可根据信号量值判断是否对公共资源具有访问的权限,当信号量值大于 0 时,则可以访问,否则将阻塞。PV 原语是对信号量的操作,一次 P 操作使信号量减1,一次 V 操作使信号量加1。
    b、函数:
    初始化信号量:sem_init、销毁信号量:sem_destroy
    信号量P操作:sem_wait、信号量V操作:sem_post、获取信号量的值:sem_getvalue
    c、适用场景
    【信号量用于同步】:

    后端知识点链接(二):操作系统、Linux
    6)无锁CAS
    7)校验方式(CRC32校验)
  • 有了互斥量,为什么还需要条件变量有了互斥量,为什么还需要条件变量/p>

  • 多进程和多线程的区别进程和多线程相比有什么好处?

    来源:杰尼鬼头大

    声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年6月10日
下一篇 2021年6月10日

相关推荐