为了做好运维面试路上的助攻手,特整理了上百道 【运维技术栈面试题集锦】 ,让你面试不慌心不跳,高薪offer怀里抱!
这次整理的面试题,小到shell、MySQL,大到K8s等云原生技术栈,不仅适合运维新人入行面试需要,还适用于想提升进阶跳槽加薪的运维朋友。
本份面试集锦涵盖了
- 174 道运维工程师面试题
- 128道k8s面试题
- 108道shell脚本面试题
- 200道Linux面试题
- 51道docker面试题
- 35道Jenkis面试题
- 78道MongoDB面试题
- 17道ansible面试题
- 60道dubbo面试题
- 53道kafka面试
- 18道mysql面试题
- 40道nginx面试题
- 77道redis面试题
- 28道zookeeper
总计 1000+ 道面试题, 内容 又全含金量又高
- 174道运维工程师面试题
1、什么是运维?
2、在工作中,运维人员经常需要跟运营人员打交道,请问运营人员是做什么工作的?
3、现在给你三百台服务器,你怎么对他们进行管理?
4、简述raid0 raid1raid5二种工作模式的工作原理及特点
5、LVS、Nginx、HAproxy有什么区别?工作中你怎么选择?
6、Squid、Varinsh和Nginx有什么区别,工作中你怎么选择?
7、Tomcat和Resin有什么区别,工作中你怎么选择?
8、什么是中间件?什么是jdk?
9、讲述一下Tomcat8005、8009、8080三个端口的含义?
10、什么叫CDN?
11、什么叫网站灰度发布?
12、简述DNS进行域名解析的过程?
13、RabbitMQ是什么东西?
14、讲一下Keepalived的工作原理?
15、讲述一下LVS三种模式的工作过程?
16、mysql的innodb如何定位锁问题,mysql如何减少主从复制延迟?
17、如何重置mysql root密码?
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
文章目录
- 一、什么是进程
- 二、进程管理
- 三、通过系统调用函数获取进程标示符PID和PPID
- 四、fork创建子进程
- 五、进程状态
- 六、kill杀死(中断)进程
- 七、Z 僵尸进程
- 八、孤儿进程
- 九、进程优先级
- 十、补充几个概念
一、什么是进程
程序本质上是一个包含可执行代码的文件,是一个放在磁盘上的静态文件。当我们双击这个可执行程序将其运行起来时,本质上是将这个程序加载到内存当中,此时这个程序就被称为进程。所以进程就是一个开始执行但是还没有结束的程序的实例,是可执行文件的具体实现。当程序被系统调用到内存以后,系统会给程序分配一定的资源(内存、设备等)然后进行一系列的复杂操作,使程序变成进程以供系统调用。
综上所述,进程是程序的一次执行过程和资源分配的基本单位。
区分程序和进程:
程序:程序本质是一个放在磁盘上的静态文件。
进程:程序运行起来之后,就叫做进程,进程是动态的,由操作系统管理。
二、进程管理
操作系统允许多个进程同时运行,此时就需要操作系统对进程进行管理,管理的核心也是先描述,再组织:所以对进程的管理,会转化成对由进程控制块(PCB)组成的链表的管理(增删查改)。
进程信息包括对应的文件+进程属性。进程属性是方便操作系统对进程进行管理,所以进程信息的大小要比原本的文件要大。
创建一个进程实际上就是先将该进程的代码和数据加载到内存,紧接着操作系统对该进程进行描述形成对应的PCB,并将这个PCB插入到该双链表当中。而退出一个进程实际上就是先将该进程的PCB从该双链表当中删除,然后操作系统再将内存当中属于该进程的代码和数据进行释放或是置为无效。
综上所述,进程就是可执行程序与管理进程需要的数据的集合。
2.1.描述进程–PCB
PCB的全称为Process Ctrl Block(进程控制块)。
具体操作系统的PCB名字是不同的,由于Linux操作系统是用C语言进行编写的,因此Linux当中的PCB是由结构体实现的–struct task_struct()
。
task_struct
当中主要包含以下信息:
- 标示符: 描述本进程的唯一标示符,用来区别其他进程:Pid和PPid。
- 状态: 任务状态,退出代码,退出信号等。并不是所有的进程都是运行的,也有的进程是在等待运行,此时就需要状态信息。
- 优先级: 相对于其他进程的优先级。
- 程序计数器: 程序中即将被执行的下一条指令的地址。
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
- I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
- 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
- 其他信息
2.2.查看进程
2.2.1.使用ps命令查看
通过 ps
(process status)命令可以显示当前进程的状态,类似于 windows 的任务管理器。
它的参数比较多,常用的有:
- -e 列出所有的进程
- -f:全格式
- -h:不显示标题
- -l:长格式
- -w: 宽输出,显示加宽可以显示较多的资讯
- a:显示终端上的所有进程,包括其他用户的进程
- r:只显示正在运行的进程
- x:显示没有控制终端的进程
- u:试用用户格式输出
- j:采用工作控制的格式显示进程状况。
- l:采用详细的格式来显示进程状况。
比较常用的是a、u、x三个选项。
以ps -aux
为例:
USER: 行程拥有者
PID: 进程的ID号,用来识别进程
%CPU: 占用的 CPU 使用率
%MEM: 占用的记忆体使用率
VSZ: 占用的虚拟记忆体大小
RSS: 占用的记忆体大小
TTY: 终端的次要装置号码
STAT: 该进程的状态
START: 进程开始时间
TIME: 执行的时间
COMMAND:所执行的指令
ps命令与grep命令搭配使用,即可只显示某一进程的信息。
以下面的mybin
程序为例:
ps aux | head -1 &&ps aux | grep mybin | grep -v grep
:
其中ps aux | head -1
是为了显示第一行属性,ps aux | grep mybin | grep -v grep
是为了过滤出mybin
程序并且屏蔽掉grep
这条命令本身。
通过kill PID
这条命令可以终止进程:
2.2.2.通过系统目录查看
在根目录下有一个名为proc
的系统文件夹,这是个动态文件系统。
文件夹当中包含大量进程信息,还有的是一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程都有对应的一个目录在/proc
下,以进程的PID
号为目录名,它们是读取进程信息的接口。
直接查看18014目录就可以查看启动这个进程所有的属性信息了。
三、通过系统调用函数获取进程标示符PID和PPID
使用系统调用函数,getpid()
和getppid()
即可分别获取进程的PID和PPID。
其中,PID是当前进程的ID号,PPID是父进程的ID号。
#include <stdio.h>
#include <unistd.h>
int main()
{
while(1)
{
printf("pid: %d\n", getpid());
printf("ppid: %d\n", getppid());
sleep(1);
}
return 0;
}
使用ps axj | head -1 &&ps axj | grep mybin | grep -v grep
通过ps查看它的父进程:
通过ps查看它的父进程:
可以看到,bash创建了mybin这个子进程,由于进程是有独立性的,子进程挂掉了,父进程bash也不会挂掉。
bash运行原理:bash叫做命令行解释器(在命令行下的所有命令几乎都是bash的子进程),bash只需要接受任务识别任务,然后创建子进程。通过创建子进程,让子进程去完成对应的任务。
这样,每次运行mybin程序虽然PID
会改变,但是父进程IDPPID
是不会变的,因为它是由bash创建的,而bash是不会终止然后重新创建的:
四、fork创建子进程
fork是一个系统调用级别的函数,其功能就是创建一个子进程。
可以看到两次输出的PID不相同,说明fork创建了一个新的进程,fork函数创建的进程的PPID就是proc进程的PID,也就是说proc进程与fork函数创建的进程之间是父子关系。
对于父进程(调用fork函数的进程),fork函数的返回值是子进程的PID,如果子进程创建失败,则在父进程中返回 -1;对于子进程创建成功则是返回0。
使用fork函数创建子进程,在fork函数被调用之前的代码被父进程执行,而fork函数之后的代码,则默认情况下父子进程都可以执行。
使用fork函数创建子进程后就有了两个进程,这两个进程被操作系统调度的顺序是不确定的,这取决于操作系统调度算法的具体实现。
由于父子进程的fork返回值不同,此时就可以使用if将父子进程分流,这样就可以实现让父子进程执行不同的代码,实现不同的功能:
父子进程都有while死循环,但是由于父子进程是独立的,所以它们可以同时各自执行自己的while死循环,并不存在先调度完父进程然后再调度子进程的情况。这也就进一步证明了子进程的运行和父进程是无关的,只是这两个进程被操作系统调度的顺序是不确定的,取决于操作系统调度算法的具体实现。
4.1.补充内容
- fork创建子进程以后,系统就要多一组进程管理的数据结构(操作系统为了管理这个进程就得新创建一个数据结构)以及该进程对应的代码和数据(子进程要执行的代码)。其实就是创建一个新的PCB插入到任务队列(链表)中。
- 父子进程的代码是共享的,但是父子进程的数据各自开辟空间并且各自私有(采用写时拷贝)这样就表现出父子进程的独立性。
- 至于为什么fork会有两个返回值(子进程的PID和0),其实并不是一次返回两个返回值,而是从一个进程变成两个进程,每个进程的返回值不一样。
五、进程状态
要对进程进行监测和控制,首先必须要了解当前进程运行状态的情况,下面是kernel源代码中定义的状态:
/\*
\* The task state array is a strange "bitmap" of
\* reasons to sleep. Thus "running" is zero, and
\* you can test for combinations of others with
\* simple bit tests.
\*/
static const char \* const task_state_array[] = {
"R (running)", /\* 0 \*/
"S (sleeping)", /\* 1 \*/
"D (disk sleep)", /\* 2 \*/
"T (stopped)", /\* 4 \*/
"t (tracing stop)", /\* 8 \*/
"X (dead)", /\* 16 \*/
"Z (zombie)", /\* 32 \*/
};
其中:
R :可执行状态。
S:可中断的睡眠状态。
D:不可中断的睡眠状态。
T/t:暂停状态或跟踪状态。
X:死亡状态,进程即将被销毁。
Z :退出状态,进程成为僵尸进程。
进程的退出状态是会被保存PCB也就是task_struct
中的。
R 可执行状态
只有在该状态的进程才可能在CPU上运行。处于这个状态的进程的PCB被放入对应CPU的可执行队列中(一个进程最多只能出现在一个CPU的可执行队列中)。进程调度器的任务就是从各个CPU的可执行队列中分别选择一个进程在该CPU上运行。所以处于这个状态并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里等待被调度。
S 可中断睡眠状态
处于这个状态的进程因为等待某某事件的发生(比如等待socket连接、等待信号量),而被挂起。这些进程的PCB结构被放入对应事件的等待队列中。当这些事件发生时(由外部中断触发、或由其他进程触发),对应的等待队列中的一个或多个进程将被唤醒。这样就实现了处于浅度睡眠状态的进程随时可以被唤醒,也可以被杀掉。
上面的循环打印PID的程序就是这样:
因为这个进程是在等待IO(往显示器输入数据)的。
如果状态中有+
则表示这个进程是在前台运行的,此时可以直接Ctrl+c
终止进程,如果在执行程序时加上&符:./proc &
,则表示将程序放到后台运行,此时无法直接使用Ctrl+c
终止进程,只能使用kill -9 PID
的方式。
先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前在阿里
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
图片转存中…(img-Avvb4Whg-1715316468607)]
[外链图片转存中…(img-1FH87NUL-1715316468608)]
[外链图片转存中…(img-90uK21yn-1715316468608)]
[外链图片转存中…(img-RiAPlcmc-1715316468608)]
[外链图片转存中…(img-sb4tWXoq-1715316468609)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新