操作系统
1.如何查看系统中的内存状态
2.Linux指令:查看进程状态?查看文件信息?查看内存使用?查看磁盘占有量?Grep指令的原理;
top命令:Linux top命令小结 - 简书
grep命令:Linux下的grep命令详解_学如逆水行舟的技术博客_51CTO博客_grep命令详解
查看磁盘:linux查看磁盘使用情况命令_陈袁的博客-优快云博客_linux 查看磁盘
3.操作系统:进程与线程的区别?Linux系统中两者有区别吗?软链接与硬链接的区别(不会)?用户态与内核态的区别(用读文件举例说明)?
4.死锁的原因
操作系统------死锁的条件和解决方法_ZJE-优快云博客
面试问题之操作系统:死锁的四个必要条件和解决办法 - 知了会爬树 - 博客园
5.虚拟内存
在现代操作系统中,进程之间共享使用cpu和内存,但是内存资源有限,为了更加高效地使用内存,现代操作系统提供一个内存抽象—虚拟内存。虚拟内存巧妙地利用内存,地址转换,磁盘文件和操作系统内核来为每一个进程提供足够大的统一的私有地址空间。虚拟内存提供三个重要的能力:1)将内存当作磁盘的缓存,在内存中只保留常用数据,必要时从内存和磁盘之间交换数据。2)简化内存管理,为每个进程提供统一的地址空间。3)保护进程的内存空间不受其他进程影响。
6.常见排序算法,排序算法稳定的意思,快排的复杂度什么时候退化,基本有序用什么
7.进程线程,虚拟内存,页面置换
8.内存访问磁盘数据
9.epoll
10.内核态用户态的区别
用户态(user mode) : 用户态运行的进程或可以直接读取用户程序的数据。
内核态(kernel mode):可以简单的理解系统态运行的进程或程序几乎可以访问计算机的任何资源,不受限制。
用户态到内核态具体的切换步骤:
(1)从当前进程的描述符中提取其内核栈的ss0及esp0信息。
(2)使用ss0和esp0指向的内核栈将当前进程的cs,eip,eflags,ss,esp信息保存起来,这个过程也完成了由用户栈到内核栈的切换过程,同时保存了被暂停执行的程序的下一条指令。
(3)将先前由中断向量检索得到的中断处理程序的cs,eip信息装入相应的寄存器,开始执行中断处理程序,这时就转到了内核态的程序执行了。
ss0是任务内核态堆栈的段选择符,esp0是堆栈栈底指针
11.描述并写一下LRU
12.进程间通信的共享内存,如何保证安全性,结合epoll讲讲共享内存;共享内存通信方式
用信号量来实现使用共享内存的不同进程间的同步工作。
(1)锁。操作系统为我们提供了多种类型的锁,诸如互斥锁、读写锁、自旋锁等。互斥锁(pthread_mutex_t)可以保证线程间的互斥锁,通过设置互斥锁的进程间共享属性,可以实现进程间共用互斥锁。相应地,我们可以将读写锁、自旋锁改造为多进程共享的。这种方式有一个隐患:当加锁进程异常退出时,其他进程可能永远无法抢到锁。
(2)信号量也是一个常见的多进程同步方式。通过semget或者sem_open打开一个信号量,然后通过PV操作来达到进程间互斥的效果。但是信号量也存在加锁进程异常退出时,不能自动解锁的问题。
(3)文件记录锁可以锁定文件的一部分或者全部。假设我们将文件与共享内存中的数据块对应起来,则可以通过文件锁来同步共享内存的读写操作。值得说明的时,当进程异常退出时,该进程持有的文件锁会自动释放。相对于信号量,文件锁的效率稍差。
共享内存的数据同步 - 程序园
linux实现共享内存同步的四种方法_sunxiaopengsun的专栏-优快云博客_共享内存同步机制
13.Pipe和fifo的区别
14.硬连接/软连接
硬链接: 硬连接指通过索引节点 inode 来进行的连接,即每一个硬链接都是一个指向对应区域的文件。
软链接: 保存了其代表的文件的绝对路径,是另外一种文件,在硬盘上有独立的区块, 访问时替换自身路径。
Linux硬链接和软连接的区别与总结 - Hsia的博客 | Hsia Blog
Linux软连接和硬链接 - iTech - 博客园
15.查看文件指定某一行。
sed -n ‘10p’ test_classification.py
sed -n ‘10,20p’ test_classification.py
16.查看端口占用
lsof -i:端口号 用于查看某一端口的占用情况,比如查看8000端口使用情况,lsof -i:8000
netstat -tunlp |grep 端口号,用于查看指定的端口号的进程情况,如查看8000端口的情况,netstat -tunlp |grep 8000
Linux 查看端口占用情况 - 菜鸟++ - 博客园
17.如何查看日志
head\tail\cat\less\more
18.什么是线程不安全
19.什么是IO复用,什么是非阻塞IO
20.select\poll\epoll
Netty——(3)高并发编程必备知识IO多路复用技术select、poll、epoll分析_探索的小白-优快云博客
IO多路复用之select、poll、epoll - Yungyu - 博客园
21.线程共享进程的资源里的局部变量等属于堆还是栈
22.linux怎么查看内存泄漏
使用mtrace命令:利用linux的mtrace命令定位内存泄露(Memory Leak)_zpznba的博客-优快云博客
使用 Valgrind工具:linux下内存泄露查找、BUG调试 | 学步园
感觉两个工具一样的,都是编译的时候加上-g参数,然后调用工具进行查看
23.如何清除已出现的僵尸进程?
用ps 命令和 grep命令寻找僵尸进程:
ps -A -ostat,ppid,pid,cmd | grep -e ‘1’
命令注解:
-A 参数列出所有进程
-o 自定义输出字段,我们设定显示字段为stat(状态),ppid(父进程pid),pid(进程pid),cmd(命令行)这四个参数
因为状态为 z 或者 Z的进程为僵尸进程,所以我们使用grep 抓取stat 状态为zZ进程;
清除僵尸进程的话可以kill掉僵尸进程的父进程。
24.线程、进程上下文切换;为什么线程切换比进程快
操作系统保持跟踪进程运行所需的所有状态信息,这种状态,也就是上下文,它包括许多信息,例如PC和寄存器文件的当前值,以及主存的内容。
操作系统实现这种交错执行的机制称为上下文切换。
当操作系统决定要把控制权从当前进程转移到某个新进程时,就会进行上下文切换,即保存当前进程的上下文,恢复新进程的上下文,然后将控制权传递到新进程,新进程就会从上次停止的地方开始
进程切换分两步:
1.切换页目录以使用新的地址空间
2.切换内核栈和硬件上下文
对于linux来说,线程和进程的最大区别就在于地址空间,对于线程切换,第1步是不需要做的,第2是进程和线程切换都要做的。
切换的性能消耗:
1、线程上下文切换和进程上下问切换一个最主要的区别是线程的切换虚拟内存空间依然是相同的,但是进程切换是不同的。这两种上下文切换的处理都是通过操作系统内核来完成的。内核的这种切换过程伴随的最显著的性能损耗是将寄存器中的内容切换出。
2、另外一个隐藏的损耗是上下文的切换会扰乱处理器的缓存机制。简单的说,一旦去切换上下文,处理器中所有已经缓存的内存地址一瞬间都作废了。还有一个显著的区别是当你改变虚拟内存空间的时候,处理的页表缓冲(processor’s Translation Lookaside Buffer (TLB))或者相当的神马东西会被全部刷新,这将导致内存的访问在一段时间内相当的低效。但是在线程的切换中,不会出现这个问题。
上下文就是内核重新启动一个被抢占的进程所需的状态。包括一下内容:
通用目的寄存器
浮点寄存器
程序计数器
用户栈
状态寄存器
内核栈
各种内核数据结构:比如描绘地址空间的页表,包含有关当前进程信息的进程表,以及包含进程已打开文件的信息的文件表。
进程切换与线程切换的一个最主要区别就在于进程切换涉及到虚拟地址空间的切换而线程切换则不会。因为每个进程都有自己的虚拟地址空间,而线程是共享所在进程的虚拟地址空间的,因此同一个进程中的线程进行线程切换时不涉及虚拟地址空间的转换。
为什么虚拟地址切换很慢
现在我们已经知道了进程都有自己的虚拟地址空间,把虚拟地址转换为物理地址需要查找页表,页表查找是一个很慢的过程,因此通常使用Cache来缓存常用的地址映射,这样可以加速页表查找,这个cache就是TLB,Translation Lookaside Buffer,我们不需要关心这个名字只需要知道TLB本质上就是一个cache,是用来加速页表查找的。由于每个进程都有自己的虚拟地址空间,那么显然每个进程都有自己的页表,那么当进程切换后页表也要进行切换,页表切换后TLB就失效了,cache失效导致命中率降低,那么虚拟地址转换为物理地址就会变慢,表现出来的就是程序运行会变慢,而线程切换则不会导致TLB失效,因为线程线程无需切换地址空间,因此我们通常说线程切换要比较进程切换块,原因就在这里。
https://segmentfault.com/a/1190000019750164
25.操作系统进程状态有哪些
状态 说明
R running or runnable (on run queue)
正在执行或者可执行,此时进程位于执行队列中。
D uninterruptible sleep (usually I/O)
不可中断阻塞,通常为 IO 阻塞。
S interruptible sleep (waiting for an event to complete)
可中断阻塞,此时进程正在等待某个事件完成。
Z zombie (terminated but not reaped by its parent)
僵死,进程已经终止但是尚未被其父进程获取信息。
T
stopped (either by a job control signal or because it is being traced)
结束,进程既可以被作业控制信号结束,也可能是正在被追踪。
D和S的区别是:
进程处于睡眠状态,但是此刻进程是不可中断的。不可中断,指的并不是CPU不响应外部硬件的中断,而是指进程不响应异步信号。绝大多数情况下,进程处在睡眠状态时,总是应该能够响应异步信号的。 而TASK_UNINTERRUPTIBLE状态存在的意义就在于,内核的某些处理流程是不能被打断的。如果响应异步信号,程序的执行流程中就会被插入一段用于处理异步信号的流程(这个插入的流程可能只存在于内核态,也可能延伸到用户态),于是原有的流程就被中断了。在进程对某些硬件进行操作时(比如进程调用read系统调用对某个设备文件进行读操作,而read系统调用最终执行到对应设备驱动的代码,并与对应的物理设备进行交互),可能需要使用TASK_UNINTERRUPTIBLE状态对进程进行保护,以避免进程与设备交互的过程被打断,造成设备陷入不可控的状态。
Linux进程状态解析 之 R、S、D、T、Z、X (主要有三个状态)_sdkdlwk的博客-优快云博客_进程状态
26.进程、线程调度算法
1.先来先服务 first-come first-serverd(FCFS)
2.短作业优先 shortest job first(SJF)
3.最短剩余时间优先 shortest remaining time next(SRTN)
4. 时间片轮转
5.优先级调度
6.多级反馈队列
计算机操作系统 - 进程管理 | CS-Notes
27.线程同步方式、线程通信
线程同步方式:互斥量、信号量、临界区、事件
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。
内核模式下的方法有:事件,信号量,互斥量。
临界区
保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么 在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操 作共享资源的目的。 仅能在同一进程内使用
互斥量 Mutex
互斥量跟临界区很相似,只有拥有互斥对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。
信号量
信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源 ,这与操作系统中的PV操作相同。
事件(Event)
事件机制,则允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务。
线程同步方式比较 - 王小北 - 博客园
28.为什么会发生进程切换,为什么不让一个进程跑下去
29.为什么cpu调度进程要用时间片轮转
30.linux用什么调度算法
完全公平调度算法CFS
进程管理笔记三、完全公平调度算法CFS_邓博学习笔记-优快云博客_完全公平调度算法
31.字节序
32.同步、异步;阻塞、非阻塞;区别
同步/异步关注的是消息通信机制 (synchronous communication/ asynchronous communication) 。
所谓同步,就是在发出一个调用时,在没有得到结果之前, 该调用就不返回。
异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果
阻塞/非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
33.实现memcpy
34.内存管理,虚拟内存
内存管理方式主要分为:页式管理、段式管理和段页式管理。
页式管理的基本原理是将各进程的虚拟空间划分为若干个长度相等的页。把内存空间按页的大小划分为片或者页面,然后把页式虚拟地址与内存地址建立一一对应的页表,并用相应的硬件地址转换机构来解决离散地址变换问题。页式管理采用请求调页和预调页技术来实现内外存存储器的统一管理。
优点:没有外碎片,每个内碎片不超过页的大小。
缺点:程序全部装入内存,要求有相应的硬件支持,如地址变换机构缺页中断的产生和选择淘汰页面等都要求有相应的硬件支持。增加了机器成本和系统开销。
段式管理的基本思想是把程序按内容或过程函数关系分成段,每段有自己的名字。一个用户作业或者进程所包含的段对应一个二维线性虚拟空间,也就是一个二维虚拟存储器。段式管理程序以段为单位分配内存,然后通过地址映射机构把段式虚拟地址转换为实际内存物理地址。
优点:可以分别编写和编译,可以针对不同类型的段采取不同的保护,可以按段为单位来进行共享,包括通过动态链接进行代码共享。
缺点:会产生碎片。
段页式管理,系统必须为每个作业或者进程建立一张段表以管理内存分配与释放、缺段处理等。另外由于一个段又被划分为若干个页,每个段必须建立一张页表以把段中的虚页变换为内存中的实际页面。显然与页式管理时相同,页表也要有相应的实现缺页中断处理和页面保护等功能的表项。
段页式管理是段式管理和页式管理相结合而成,具有两者的优点。
由于管理软件的增加,复杂性和开销也增加。另外需要的硬件以及占用的内存也有所增加,使得执行速度下降。
虚拟内存是一种内存管理思想。
35.自旋锁,互斥锁的区别
互斥锁:线程会从sleep(加锁)——>running(解锁),过程中有上下文的切换,cpu的抢占,信号的发送等开销;
自旋锁:线程一直是running(加锁——>解锁),死循环检测锁的标志位,机制不复杂,主要用于SMP和内核可抢占下,因为在内核不可抢占下,cpu在执行空操作。
互斥锁的起始原始开销要高于自旋锁,但是基本是一劳永逸,临界区持锁时间的大小并不会对互斥锁的开销造成影响,而自旋锁是死循环检测,加锁全程消耗cpu,起始开销虽然低于互斥锁,但是随着持锁时间,加锁的开销是线性增长
36.进程退出,线程会怎么样
如果是主线程调用pthread_exit退出,则不会影响其它线程;如果调用return或者是exit函数,则会杀死其它线程。
主线程、子线程与进程的退出问题_qq_34352738的博客-优快云博客_进程退出时线程退出吗
37.磁盘读写过程
磁盘读写过程_zhudinglym的博客-优快云博客
38.限流算法
常用4种限流算法介绍及比较_Solin的博客-优快云博客_限流算法
39.堆和栈的速度比较
1.分配和释放,堆在分配和释放时都要调用函数(MALLOC,FREE),比如分配时会到堆空间去寻找足够大小的空间(因为多次分配释放后会造成空洞),这些都会花费一定的时间,具体可以看看MALLOC和FREE的源代码,他们做了很多额外的工作,而栈却不需要这些。
2.访问时间,访问堆的一个具体单元,需要两次访问内存,第一次得取得指针,第二次才是真正得数据,而栈只需访问一次。另外,堆的内容被操作系统交换到外存的概率比栈大,栈一般是不会被交换出去的。
综上所述,站在操作系统以上的层面来看,栈的效率比堆高,对于应用程序员,这些都是透明的,操作系统做了很多我们看不到的东西。
1、管理方式不同;
2、空间大小不同;
3、能否产生碎片不同;
4、生长方向不同;
5、分配方式不同;
6、分配效率不同;
管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
空间大小:一般来讲在 32 位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。当然,我们可以修改:打开工程,依次操作菜单如下:Project->Setting->Link,在 Category 中选中 Output,然后在 Reserve 中设定堆栈的最大值和 commit。注意:reserve 最小值为 4Byte;commit 是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。
碎片问题:对于堆来讲,频繁的 new/delete 势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详细的可以参考数据结构,这里我们就不再一一讨论了。
生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由 malloc 函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是 C/C++ 函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
C++内存分配方式详解——堆、栈、自由存储区、全局/静态存储区和常量存储区 - 盗艹人 - 博客园
40.awk命令
linux awk命令详解 - ggjucheng - 博客园
41.共享内存如何实现;共享内存为什么是IPC中最快的通讯方式
相比较其他的进程通信方式,共享内存确实是最快的,比如说,管道通信,管道通信需要两次数据拷贝的过程.以进程1 和进程2实现进程间通信为例,进程1 和进程2 要想进行进程间通信,首先进程1 需要将数据从用户态空间拷贝到,内核态空间,接着进程2 从内核态空间中将数据拷贝到进程2中,于是进程间通信完成了.,然而共享内存就没有数据的拷贝过程,因此效率最高.
共享内存-------进程间最快的通信方式_zwq68的博客-优快云博客
45.一个进程启动时的内存管理是怎样的?
46.开机过程
① 开机访问0xFFFF0地址
② 跳转到BIOS ROM的初始化程序
③ 把BIOS ROM中的初始化程序复制到内存中执行
④ 初始化程序 首先初始化硬件,然后在硬盘中找到 引导程序。
⑤ 将引导程序复制到 内存的 0x07c00,并执行
⑥ 引导程序 将硬盘的内容复制到内存中。
⑦ 跳到内存中操作系统的开始地址,
⑧ 开始执行操作系统。
47.ctrl+c,发生了什么
我们平时在程序运行的时候按下ctrl-c、ctrl-z或者kill一个进程的时候其实都等效于向这个进程发送了一个特定信号,当进程捕获到信号后,进程会被中断并立即跳转到信号处理函数。默认情况下一个程序对ctrl-c发出的信号(SIGINT)的处理方式是退出进程,所以当我们按下ctrl-c的时候就可以终止一个进程的运行。
48.零拷贝原理
原来 8 张图,就可以搞懂「零拷贝」了 - 小林coding - 博客园
浅析Linux中的零拷贝技术 - 简书
49.程序用户空间中虚拟内存地址怎么映射到物理内存地址的
程序产生虚拟地址(由段选择符和段内偏移地址组成的地址),CPU要利用其段式内存管理单元,先将为逻辑地址转换成一个线性地址,再利用其页式内存管理单元,转换为最终物理地址。MMU就是内存管理单元。
虚拟地址指由程序产生的由段选择符和段内偏移地址组成的地址。
逻辑地址指由程序产生的段内偏移。有时候直接把逻辑地址当做虚拟地址。
线性地址指虚拟地址到物理地址变换的中间层,是处理器可寻址的内存空间中的地址。程序代码会产生逻辑地址,也就是段中的偏移地址,加上相应的段基址就成了线性地址。如果开启了分页机制,那么线性地址需要再经过变换,转为为物理地址。如果无分页机制,那么线性地址就是物理地址。
物理地址指CPU外部地址总线上寻址物理内存的地址信号,是地址变换的最终结果。
虚拟地址到物理地址的转化是体系结构相关的,一般由分段和分页两种方式。以X86CPU为例,分段和分页都是支持的。内存管理单元负责从虚拟地址到物理地址的转化。逻辑地址是段标识+段内偏移的形式。MMU通过查询段表,可以将逻辑地址转化为线性地址。无分页机制时,线性地址就是物理地址,有分页时,MMU还需要查询页表来将线性地址转化为物理地址:逻辑地址(段表)->线性地址(页表)->物理地址。
映射是一种多对一的关系,即不同的逻辑地址可以映射到同一个线性地址上;不同的线性地址也可以映射到同一个物理地址上。而且,同一个线性地址在换页之后,可能被装载到另一个物理地址上,所以这种多对一的映射关系会随时间发生变化
段表+单层页表
进程的内存先分成多个段,每个段再按照页来分配。地址分三个部分:段号+页号+页内偏移,根据段号去段表里面找对应的页表地址,得到页表的地址后,根据页号找到对应的物理内存的Page Frame地址,最后再结合页内偏移计算得到实际地址,其中段表中的Size是指某一段对应的页表的长度,即物理页的数目。以32位虚拟地址空间,4KB大小的Page为例,前10bit用于段号,中间10位用于页号,后12位用于页内偏移,假设页表的每一行的大小是4个字节,则一个物理Page Frame正好可以容下每个段的页表。
详解内存虚拟地址到物理地址的转换过程以及对应的应用场景 - 知乎
50.io密集型、cpu密集型任务分别用多进程、多线程、多协程?
对于IO密集型任务,由于CPU经常需要等待IO操作完成,因此,在等待过程中,CPU可以去做其他事情,因此采用多线程可以提高程序执行效率,这实质是并发处理。当然,由于多进程可以利用多核CPU真正实现并行处理,所以,采用多进程也可以提高IO密集型任务的执行效率。但是考虑到多线程是共享资源的,因此通信更方便,而多进程之间的资源相互独立,通信不是很方便,因此,综合来看,IO密集型任务,采用python多线程更合适。
对于计算密集型任务,由于python多线程为了实现同步锁安全机制,采用了全局锁机制,导致即使是多核CPU或多个CPU,同一时间,也只有一个线程在执行,因为全局锁只有一个,即在多核CPU或多个CPU情况下,python多线程仍然只能并发处理,而不能并行处理。而因为计算密集型任务,CPU几乎不存在空闲时间,使用python多线程,CPU频繁在各个线程之间切换所需时间反而会大大降低程序执行效率。而采用python多进程,可以实现真正意义上的并行处理,因此,计算密集型任务,采用python多进程更合适。
51.怎么实现一个协程?
52.out of memory,这个和虚拟内存的使用矛盾吗
53.Epoll的ET模式如果没读完/写完怎么办
54.Linux如何查看进程打开文件数量
55.操作系统锁和数据库锁
操作系统:自旋锁(spinlock)和mutex
死锁和活锁:活锁就是不断请求cpu
聊聊常见的锁 · Martian’S Blog
56.活锁
活锁和死锁产生的条件一样,只是表现不同。死锁下线程进入等待状态,而活锁下线程仍然处于运行状态尝试获取锁。活锁下线程仍然消耗CPU,
57.函数调用:腾讯 Linux C/C++ 后台开发实习生技能要求_技术交流_牛客网
58.进程间通信方式底层分别怎么实现
操作系统中锁的原理 - 简书
59.线程之间的栈能否通信,如何通信,数据互通吗?
60.客户端发送一个请求,服务器突然挂掉了,客户端会怎么样,为什么
61.如何不通过发送包里的信息保证服务器知道是哪一个客户端发送的
62.除了互斥锁你还能用什么方法来实现线程同步
63PV操作如何实现的
64.共享内存在哪,有什么用,底层是如何实现的
进程间通信系列(12)共享内存的基本概念_洪流之源-优快云博客
65.共享内存能放什么样的数据结构,是用什么数据结构实现的
66.共享内存里能放vector吗,为什么
67.float是如何存储的,补码反码相关问题
68.虚拟内存置换的方式,windows用的什么算法
69.如果我要进程共享地址空间,有哪些方式,具体说
70.线程上下文切换原理,切换了什么?
71.io 模型的优劣,为什么用 epoll,逐个分析
72.为什么用红黑树管理定时器,
73.还有什么其他方式?
74.分析各个方法管理定时器的优缺点?
75守护进程(创建过程有两个fork)
指在后台运行的,没有控制终端与之相连的进程。它独立于控制终端,周期性地执行某种任务。Linux的大多数服务器就是用守护进程的方式实现的,如web服务器进程http等
创建守护进程要点:
(1)让程序在后台执行。方法是调用fork()产生一个子进程,然后使父进程退出。
(2)调用setsid()创建一个新对话期。控制终端、登录会话和进程组通常是从父进程继承下来的,守护进程要摆脱它们,不受它们的影响,方法是调用setsid()使进程成为一个会话组长。setsid()调用成功后,进程成为新的会话组长和进程组长,并与原来的登录会话、进程组和控制终端脱离。
(3)禁止进程重新打开控制终端。经过以上步骤,进程已经成为一个无终端的会话组长,但是它可以重新申请打开一个终端。为了避免这种情况发生,可以通过使进程不再是会话组长来实现。再一次通过fork()创建新的子进程,使调用fork的进程退出。
(4)关闭不再需要的文件描述符。子进程从父进程继承打开的文件描述符。如不关闭,将会浪费系统资源,造成进程所在的文件系统无法卸下以及引起无法预料的错误。首先获得最高文件描述符值,然后用一个循环程序,关闭0到最高文件描述符值的所有文件描述符。
(5)将当前目录更改为根目录。
(6)子进程从父进程继承的文件创建屏蔽字可能会拒绝某些许可权。为防止这一点,使用unmask(0)将屏蔽字清零。
(7)处理SIGCHLD信号。对于服务器进程,在请求到来时往往生成子进程处理请求。如果子进程等待父进程捕获状态,则子进程将成为僵尸进程(zombie),从而占用系统资源。如果父进程等待子进程结束,将增加父进程的负担,影响服务器进程的并发性能。在Linux下可以简单地将SIGCHLD信号的操作设为SIG_IGN。这样,子进程结束时不会产生僵尸进程。
https://segmentfault.com/a/1190000022770900
76.多进程架构与多线程架构有什么区别
Oracle的Unix/Linux版本采用多进程架构,不同的功能模块由不同的进程负责,Windows版本采用单进程多线程架构,所有的模块所在线程处在同一个进程当中。
我们来看一下区别:
1.进程管理。Oracle某个模块挂起了,没有响应,万般无奈你要重起这个模块,Unix平台只要重起这个模块所在的那个进程就可以了,其它进程保持运行,而Windows平台只有一个进程,只能影响所有模块,重启过程中所有模块都不能提供服务。
2.内存空间。每个进程拥有自己的地址空间,如果只有一个进程,所有模块共享/约束在同一空间,如果采用多进程,所有进程地址空间独立,软件申请/管理更多内存的可能和能力变大了。
3.线程间通信。因为单进程共享地址空间,进程内线程通信效率很高,不同进程的线程之间通信需要某种IPC手段,效率相比降低。其实Linux平台没有传统意义的“线程”,所有都是进程,我们看到的进程是一个进程组,里面的“线程”就是组成这个进程组的进程。
4.资源管理。单进程中其中一个线程操作文件句柄阻塞了,会影响到其它线程对这个句柄的操作,多进程无此问题。一个进程同时打开的句柄是受限制的,多进程意味着可使用更多资源。
5.运行调度。一个线程Hang了就是这个进程Hang了,一个线程Crash了就是这个进程Crash了,所以多线程要格外小心了,多进程分摊风险更安全。
6.软件开发管理。多进程可以分别交给不同团队开发,多线程分别交给不同团队开发很困难,编译要同步,Debug要同步,进程Crash了是哪个团队的责任往往要花半天时间。等等。
Oracle的这种思维主要是由资源使用决定的,单进程无法满足内存,句柄的使用需求时,只能采用多进程。而Windows微内核结构动态创建进程做得不够好,线程是更好选择,Linux宏内核结构并且线程本来就是通过进程组的方式实现的。
结论是首先由项目规模决定,这是刚需,再者由运行的系统平台决定,非刚需。
77.原子操作如何实现
处理器使用基于对缓存加锁或总线加锁的方式来实现多处理器之间的原子操作。
1.所谓总线锁就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该处理器可以独占共享内存。
2.所谓“缓存锁定”是指内存区域如果被缓存在处理器的缓存行中,并且在Lock操作期间被锁定,那么当它执行锁操作回写到内存时,处理器不在总线上声言LOCK#信号,而是修改内部的内存地址,并允许它的缓存一致性机制来保证操作的原子性,因为缓存一致性机制会阻止同时修改由两个以上处理器缓存的内存区域数据,当其他处理器回写已被锁定的缓存行的数据时,会使缓存行无效
78.缺页中断
缺页中断(英语:Page fault,又名硬错误、硬中断、分页错误、寻页缺失、缺页中断、页故障等)指的是当软件试图访问已映射在虚拟地址空间中,但是目前并未被加载在物理内存中的一个分页时,由中央处理器的内存管理单元所发出的中断。
通常情况下,用于处理此中断的程序是操作系统的一部分。如果操作系统判断此次访问是有效的,那么操作系统会尝试将相关的分页从硬盘上的虚拟内存文件中调入内存。而如果访问是不被允许的,那么操作系统通常会结束相关的进程。
要通过页面置换算法进行切换
深入理解【缺页中断】及FIFO、LRU、OPT这三种置换算法 - 云+社区 - 腾讯云
Zz ↩︎