为了做好运维面试路上的助攻手,特整理了上百道 【运维技术栈面试题集锦】 ,让你面试不慌心不跳,高薪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行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
#define QUEUE_LENGTH 10
#define ITEM_SIZE sizeof(uint8_t) // 根据实际类型选择
StaticQueue_t xQueueBuffer; // 保存队列结构体
uint8_t ucQueueStorage[QUEUE_LENGTH * ITEM_SIZE]; // 队列的buf
QueueHandle_t xQueue1 = xQueueCreateStatic( QUEUE_LENGTH,
ITEM_SIZE,
ucQueueStorage,
&xQueueBuffer );
QueueHandle_t xQueue2 = xQueueCreate( QUEUE_LENGTH,
ITEM_SIZE);
队列的读写函数如下所示:
// 写入
BaseType_t xQueueSend(QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait);
// #define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
BaseType_t xQueueSendToBack(QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait);
// #define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
BaseType_t xQueueSendToFront(QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait);
//#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT )
// 读取
BaseType_t xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait );
xQueue表示要读取或写入的队列,xTicksToWait表示等待时间。
使用队列实现同步与互斥
基本原理:队列的阻塞访问(中断的关闭与开启,链表的使用)
使用队列实现同步的示例代码如下:
/*
* Configure the clocks, GPIO and other peripherals as required by the demo.
*/
static void prvSetupHardware( void );
/*-----------------------------------------------------------*/
void vmainTask1Function( void * param);
void vmainTask2Function( void * param);
/*-----------------------------------------------------------*/
UBaseType_t task1Run = 0;
UBaseType_t task2Run = 0;
UBaseType_t taskidleRun = 0;
TaskHandle_t xTask1Handle, xTask2Handle;
int main( void )
{
QueueHandle_t xQueueHandle;
#ifdef DEBUG
debug();
#endif
prvSetupHardware();
printf("Hello world!\r\n");
xQueueHandle = xQueueCreate(1, sizeof(int));
if(0 == xQueueHandle) {
printf("create queue failed!\r\n");
}
xTaskCreate(vmainTask1Function, "task1", 100, (void *)xQueueHandle, 1, &xTask1Handle); // 动态创建任务
xTaskCreate(vmainTask2Function, "task2", 100, (void *)xQueueHandle, 1, &xTask2Handle); // 动态创建任务 // 静态创建任务
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
static void prvSetupHardware( void )
{
/* Start with the clocks in their expected state. */
RCC_DeInit();
/* Enable HSE (high speed external clock). */
RCC_HSEConfig( RCC_HSE_ON );
/* Wait till HSE is ready. */
while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET )
{
}
/* 2 wait states required on the flash. */
*( ( unsigned long * ) 0x40022000 ) = 0x02;
/* HCLK = SYSCLK */
RCC_HCLKConfig( RCC_SYSCLK_Div1 );
/* PCLK2 = HCLK */
RCC_PCLK2Config( RCC_HCLK_Div1 );
/* PCLK1 = HCLK/2 */
RCC_PCLK1Config( RCC_HCLK_Div2 );
/* PLLCLK = 8MHz * 9 = 72 MHz. */
RCC_PLLConfig( RCC_PLLSource_HSE_Div1, RCC_PLLMul_9 );
/* Enable PLL. */
RCC_PLLCmd( ENABLE );
/* Wait till PLL is ready. */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/* Select PLL as system clock source. */
RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK );
/* Wait till PLL is used as system clock source. */
while( RCC_GetSYSCLKSource() != 0x08 )
{
}
/* Enable GPIOA, GPIOB, GPIOC, GPIOD, GPIOE and AFIO clocks */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC
| RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO, ENABLE );
/* SPI2 Periph clock enable */
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );
/* Set the Vector Table base address at 0x08000000 */
NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x0 );
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
/* Configure HCLK clock as SysTick clock source. */
SysTick_CLKSourceConfig( SysTick_CLKSource_HCLK );
serialPortInit();
}
void vmainTask1Function( void * param)
{
volatile int i;
int sum = 0;
while(1) {
for(i = 0; i < 1000000; i ++) {
sum += 1;
task1Run = 1;
task2Run = 0;
taskidleRun = 0;
}
xQueueSend((QueueHandle_t)param, &sum, portMAX_DELAY);
}
}
void vmainTask2Function( void * param)
{
int readVal;
while(1) {
task1Run = 0;
task2Run = 1;
taskidleRun = 0;
xQueueReceive((QueueHandle_t)param, &readVal, portMAX_DELAY);
printf("sum = %d\r\n", readVal);
}
}
void vApplicationIdleHook( void )
{
task1Run = 0;
task2Run = 0;
taskidleRun = 1;
}
示例代码主要的功能是动态创建一个队列,任务1进行求和,求和结束后把值放入队列中,任务2 从队列中获取任务1的求和值。在任务1计算任务没有结束时,队列中没有数据,此时任务2因为队列的阻塞访问处于阻塞态;当任务1计算结束,队列中有数据,任务2由阻塞态进入就绪态(当等待的某件事发生后将退出阻塞态,可参考文章FreeRTOS学习笔记--------任务管理)并删除已读数据,最后进入运行态。实验现象如下图所示:
使用队列实现互斥的示例代码如下:
void vmainTask3Function( void * param);
void vmainTask4Function( void * param);
QueueHandle_t initLock(void);
void getLock(QueueHandle_t handle);
void putLock(QueueHandle_t handle);
int main( void )
{
QueueHandle_t xQueueLockHandle;
prvSetupHardware();
printf("Hello world!\r\n");
xQueueLockHandle = initLock();
xTaskCreate(vmainTask3Function, "task3", 100, (void *)xQueueLockHandle, 1, NULL); // 动态创建任务
xTaskCreate(vmainTask4Function, "task4", 100, (void *)xQueueLockHandle, 1, NULL); // 动态创建任务
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
static void prvSetupHardware( void )
{
/* Start with the clocks in their expected state. */
RCC_DeInit();
/* Enable HSE (high speed external clock). */
RCC_HSEConfig( RCC_HSE_ON );
/* Wait till HSE is ready. */
while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET )
{
}
/* 2 wait states required on the flash. */
*( ( unsigned long * ) 0x40022000 ) = 0x02;
/* HCLK = SYSCLK */
RCC_HCLKConfig( RCC_SYSCLK_Div1 );
/* PCLK2 = HCLK */
RCC_PCLK2Config( RCC_HCLK_Div1 );
/* PCLK1 = HCLK/2 */
RCC_PCLK1Config( RCC_HCLK_Div2 );
/* PLLCLK = 8MHz * 9 = 72 MHz. */
RCC_PLLConfig( RCC_PLLSource_HSE_Div1, RCC_PLLMul_9 );
/* Enable PLL. */
RCC_PLLCmd( ENABLE );
/* Wait till PLL is ready. */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/* Select PLL as system clock source. */
RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK );
/* Wait till PLL is used as system clock source. */
while( RCC_GetSYSCLKSource() != 0x08 )
{
}
/* Enable GPIOA, GPIOB, GPIOC, GPIOD, GPIOE and AFIO clocks */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC
| RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO, ENABLE );
/* SPI2 Periph clock enable */
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );
/* Set the Vector Table base address at 0x08000000 */
NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x0 );
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
/* Configure HCLK clock as SysTick clock source. */
SysTick_CLKSourceConfig( SysTick_CLKSource_HCLK );
serialPortInit();
}
QueueHandle_t initLock(void)
{
QueueHandle_t xQueueHandle;
int val;
xQueueHandle = xQueueCreate(1, sizeof(int));
if(0 == xQueueHandle) {
printf("create queue failed!\r\n");
return 0;
}
xQueueSend(xQueueHandle, &val, portMAX_DELAY);
return xQueueHandle;
}
void getLock(QueueHandle_t handle)
{
int val;
xQueueReceive(handle, &val, portMAX_DELAY); // 读取后,队列为空
}
void putLock(QueueHandle_t handle)
{
int val;
xQueueSend(handle, &val, portMAX_DELAY);
}
void vmainTask3Function( void * param)
{
while(1) {
getLock((QueueHandle_t)param);
printf("3\r\n");
putLock((QueueHandle_t)param);
taskYIELD();
}
}
void vmainTask4Function( void * param)
{
while(1) {
getLock((QueueHandle_t)param);
printf("4\r\n");
// 在释放前,任务3因队列中无数据处于阻塞态
putLock((QueueHandle_t)param);
// 释放后,任务3处于就绪态,任务4处于运行态
taskYIELD();
}
}
原理与实现同步相同,**需要注意的是,队列长度为1,并且释放lock需调用taskYIELD()函数让出CPU资源。**实验现象如下,任务3和4交替使用串口。
队列集
队列集允许任务从多个队列接收数据,而无需任务依次轮询每个队列以确定哪个队列(如果有的话)包含数据。
使用队列集时,读写队列的流程如下图所示:
综上所述,向队列中写N次数据,那么队列集也相应的操作N次。另外,由此不能理解,队列集中存储的是含有数据的队列的句柄,队列集长度为所有队列长度之和。
示例代码如下所示,在使用队列集前需先在FreeRTOSConfig.h中将configUSE_QUEUE_SETS配置为1。
/*
* Configure the clocks, GPIO and other peripherals as required by the demo.
*/
static void prvSetupHardware( void );
/*-----------------------------------------------------------*/
void vmainTask1Function( void * param);
void vmainTask2Function( void * param);
void vmainTask3Function( void * param);
/*-----------------------------------------------------------*/
int main( void )
{
QueueHandle_t queueHandle1, queueHandle2;
QueueSetHandle_t queueSetHandle;
prvSetupHardware();
printf("Hello world!\r\n");
/*1.创建队列*/
queueHandle1 = xQueueCreate(2, sizeof(int));
queueHandle2 = xQueueCreate(2, sizeof(int));
/*2.创建队列集,队列集长度等于所有队列长度之和*/
queueSetHandle = xQueueCreateSet(4);
/*3.将队列添加进队列集*/
xQueueAddToSet(queueHandle1, queueSetHandle);
xQueueAddToSet(queueHandle2, queueSetHandle);
xTaskCreate(vmainTask1Function, "task1", 100, (void *)queueHandle1, 1, NULL); // 动态创建任务
xTaskCreate(vmainTask2Function, "task2", 100, (void *)queueHandle2, 1, NULL); // 动态创建任务
xTaskCreate(vmainTask3Function, "task3", 100, (void *)queueSetHandle, 1, NULL); // 动态创建任务
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/
static void prvSetupHardware( void )
{
/* Start with the clocks in their expected state. */
RCC_DeInit();
/* Enable HSE (high speed external clock). */
RCC_HSEConfig( RCC_HSE_ON );
/* Wait till HSE is ready. */
while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET )
{
}
/* 2 wait states required on the flash. */
*( ( unsigned long * ) 0x40022000 ) = 0x02;
/* HCLK = SYSCLK */
RCC_HCLKConfig( RCC_SYSCLK_Div1 );
/* PCLK2 = HCLK */
RCC_PCLK2Config( RCC_HCLK_Div1 );
/* PCLK1 = HCLK/2 */
RCC_PCLK1Config( RCC_HCLK_Div2 );
/* PLLCLK = 8MHz * 9 = 72 MHz. */
RCC_PLLConfig( RCC_PLLSource_HSE_Div1, RCC_PLLMul_9 );
/* Enable PLL. */
RCC_PLLCmd( ENABLE );
/* Wait till PLL is ready. */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{
}
/* Select PLL as system clock source. */
RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK );
/* Wait till PLL is used as system clock source. */
while( RCC_GetSYSCLKSource() != 0x08 )
{
}
/* Enable GPIOA, GPIOB, GPIOC, GPIOD, GPIOE and AFIO clocks */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC
| RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | RCC_APB2Periph_AFIO, ENABLE );
/* SPI2 Periph clock enable */
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );
/* Set the Vector Table base address at 0x08000000 */
NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x0 );
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
/* Configure HCLK clock as SysTick clock source. */
SysTick_CLKSourceConfig( SysTick_CLKSource_HCLK );
**先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前在阿里**
**深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
![img](https://img-blog.csdnimg.cn/img_convert/2740b99a905338a9b86f448b1123a483.png)
![img](https://img-blog.csdnimg.cn/img_convert/f128b3624dcc5dacb1ea1e764e940af4.png)
![img](https://img-blog.csdnimg.cn/img_convert/2a360d1b430db1ab94bfab1614f81ccb.png)
![img](https://img-blog.csdnimg.cn/img_convert/e256b6803a800879c327c26ad9a603fe.png)
![img](https://img-blog.csdnimg.cn/img_convert/a2baed234b825ed28f7a66bc3eafd701.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618542503)**
节跳动等大厂,目前在阿里**
**深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**
[外链图片转存中...(img-VzIwcEFN-1715132430358)]
[外链图片转存中...(img-h3v6Tn8j-1715132430359)]
[外链图片转存中...(img-oZMhXNvL-1715132430360)]
[外链图片转存中...(img-qAIu5i7b-1715132430361)]
[外链图片转存中...(img-11wCKiVu-1715132430361)]
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618542503)**