2024年LINUX 信号处理_linux 信号处理流程,2024年最新震撼来袭

本文提供了一份详细的运维技术面试题集,涵盖Shell、MySQL、K8s等众多技术领域,旨在帮助运维人员提升技能,顺利应对面试挑战。同时强调了系统学习和知识体系的重要性。
摘要由CSDN通过智能技术生成

为了做好运维面试路上的助攻手,特整理了上百道 【运维技术栈面试题集锦】 ,让你面试不慌心不跳,高薪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行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

while(1)

sleep(1);

return 0;

}

该程序可以通过 Ctrl+\终止, 因为
组合键 Ctrl+\能够产生 SIGQUIT 信号,而该信号的捕捉函数尚未在程序中注册。

3、sigaction 信号处理机制

在 signal 处理机制下, 还有许多特殊情况需要考虑:

1、注册一个信号处理函数,并且处理完毕一个信号之后,是否需要重新注册,才能够捕捉下一个
信号;(不需要)

2、如果信号处理函数正在处理信号, 并且还没有处理完毕时,又发生了一个同类型的信号,这时
该怎么处理;(挨着执行),后续相同信号忽略(会多执行一次)。

3、如果信号处理函数正在处理信号,并且还没有处理完毕时,又发生了一个不同类型的信号,这
时该怎么处理;(跳转去执行另一个信号,之后再执行剩下的没有处理完的信号)

4、如果程序阻塞在一个系统调用(如 read(…))时,发生了一个信号,这时是让系统调用返回错误再
接着进入信号处理函数,还是先跳转到信号处理函数,等信号处理完毕后,系统调用再返回。—>  由下面具体说明:

**总结:**信号都是平等的无优先级。但是对于singal接口来说最多执行2次、打断。默认不能打断当前相同信号,可以被其他信号打断。另外一个信号会立即唤醒正在睡眠的进程。

eg:

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <signal.h>

int g_iSeq = 0;

void SignHandler(int iSignNo)

{

int iSeq = g_iSeq++;

printf(“%d Enter SignHandler,signo:%d\n”,iSeq,iSignNo);

sleep(3);

printf(“%d Leave SignHandler,signo:%d\n”,iSeq,iSignNo);

}

int main()

{

char szBuf[8];

int iRet;

//不同的信号调用同一个处理函数

signal(SIGINT,SignHandler);

signal(SIGQUIT,SignHandler);

do{

iRet = read(STDIN_FILENO,szBuf,sizeof(szBuf)-1);

if(iRet < 0){

perror(“read fail.”);

break;

}

s
zBuf[iRet] = 0;

printf(“Get: %s”,szBuf);

}while(strcmp(szBuf,“quit\n”) != 0);

return 0;

}

程序运行时,针对于如下几种输入情况,看输出结果:

1、 [CTRL+c] [CTRL+c] (一个一个挨着执行)

2、 [CTRL+c] [CTRL+] (先执行 c 的进入, 被\打断, 转而执行\,

最后执行c的退出)

3、 hello [CTRL+] [Enter] (先执行中断, 没有任何输出)

4、 [CTRL+] hello [Enter] (先执行中断, 输出内容)

5、 hel [CTRL+] lo[Enter] (先执行中断, 只输出 lo)

4、sigaction 信号处理注册

函数原型:

#include <signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

  1. sigaction 也用于注册一个信号处理函数
  2. 参数 signum 为需要捕捉的信号
  3. 参数 act 是一个结构体, 里面包含信号处理函数地址、 处理方式等信息
  4. 参数 oldact 是一个传出参数, sigaction 函数调用成功后, oldact 里面包含以前对 signum 的处理方式的信息,通常为 NULL,如果函数调用成功,将返回 0,否则返回-1

**1、**结构体 struct sigaction的原型为:

struct sigaction {

void (*sa_handler)(int); //老类型的信号处理函数指针

void (*sa_sigaction)(int, siginfo_t *,void *);//新类型的信号处理函数指针

sigset_t sa_mask;         //将要被阻塞的信号集合

int sa_flags;            
//信号处理方式掩码(SA_SIGINFO)

void(*sa_restorer)(void);       
//保留, 不要使

};

1、字段sa_handler是一个函数指针,用于指向原型为void handler(int)的信号处理函数地址,
即老类型 的信号处理函数(如果用这个再将 sa_flags = 0,就等同于 signal()函数)

2、字段 sa_sigaction 也是一个函数指针,用于指向原型为:
void handler(int iSignNum, siginfo_t *pSignInfo, void *pReserved);
的信号处理函数,即新类型的信号处理函数

  • iSignNum: 传入的信号
  • pSignInfo: 与该信号相关的一些信息,它是个结构体
  • pReserved: 保留,现没用,通常为NULL

3、字段sa_handler和sa_sigaction只应该有一个生效,如果想采用老的信号处理机制,就应该让
sa_handler指向正确的信号处理函数,并且让字段sa_flags为0;否则应该让sa_sigaction指向正确
的信号处理函数,并且让字段sa_flags包含SA_SIGINFO选项。

4、字段sa_mask是一个包含信号集合的结构体,该结构体内的信号表示在进行信号处理时,将要
被阻塞的信号。

  • 针对sigset_t 结构体,有一组专门的函数对它进行处理,它们是:#include <signal.h>
    • int sigemptyset(sigset_t *set);   //清空信号集合 set
      • int sigfillset(sigset_t *set);                           //将所有信号填充进set中
      • int sigaddset(sigset_t *set, int signum);            //往set中添加信号signum
      • int sigdelset(sigset_t *set, int signum);          //从 set 中移除信号 signum
      • int sigismember(const sigset_t *set, int signum); //判断signum是否包含在set中(是:返回1,否:0)
      • int sigpending(sigset_t *set); //将被阻塞的信号集合由参数set指针返回(挂起信号)
  • 其中,对于函数sigismember而言,如果signum在set集中,则返回 1;不在,则返回0;出错时返回-1.其他的函数都是成功返回0,失败返回-1。

eg: 如果打算在处理信号SIGINT时,只阻塞对SIGQUIT信号的处理,可以用如下方法:

struct sigaction act;

act.sa_flags = SA_SIGINFO;

act.sa_sigaction = newHandler;

sigemptyset(&act.sa_mask);

sigaddset(&act.sa_mask, SIGQUIT);

sigaction(SIGINT,&act,NULL);

5、字段 sa_flags是一组掩码的合成值,指示信号处理时所应该采取的一些行为,各掩码的含义为:

eg:用sigaction 实现和signal(只能传递一个参数)一样的功能。

#include<signal.h>

#include<stdio.h>

void handle(int signo)

{

printf(“signo: %d\n”,signo);

}

m
ain()

{

struct sigaction st;

st.sa_handler = handle;

st.sa_flags = 0;

sigaction(SIGINT,&st,NULL);

while(1)

{

sleep(1);

}

}

2、用sigaction 实现调用新的信号处理函数

#include <stdio.h>

#include <string.h>

#include <unistd.h>

#include <signal.h>

int g_iSeq = 0;

void SignHandlerNew(int iSignNo,siginfo_t *pInfo,void *pReserved)

{

int iSeq = g_iSeq++;

printf("%d Enter

SignHandlerNew,signo:%d\n",iSeq,iSignNo);

sleep(3);

printf(“%d Leave SignHandlerNew,signo:%d\n”,iSeq,iSignNo);

}

in
t main()

{

struct sigaction act;

act.sa_sigaction = SignHandlerNew;

act.sa_flags = SA_SIGINFO;

sigaction(SIGINT,&act,NULL);

sigaction(SIGQUIT,&act,NULL);

while(1)

{

sleep(1);

}

r
eturn 0;

}

5、sigprocmask 信号阻塞

函数sigaction中设置的被阻塞信号集合只是针对于要处理的信号,例如

struct sigaction act;

sigemptyset(&act.sa_mask);

sigaddset(&act.sa_mask,SIGQUIT);

sigaction(SIGINT,&act,NULL);

表示只有在处理信号SIGINT时,才阻塞信号 SIGQUIT;(重点区分)

函数sigprocmask 是全程阻塞,在 sigprocmask 中设置了阻塞集合后, 被阻塞的信号将不能再被信号
处理函数捕捉,直到重新设置阻塞信号集合。

原型为:

#include <signal.h>

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

参数 how 的值为如下3者之一:

a: SIG_BLOCK ,将参数 2 的信号集合添加到进程原有的阻塞信号集合中

b: SIG_UNBLOCK ,从进程原有的阻塞信号集合移除参数2中包含的信号

c: SIG_SETMASK, 重新设置进程的阻塞信号集为参数 2 的信号集

参数 set 为阻塞信号集

参数 oldset 是传出参数, 存放进程原有的信号集, 通常为 NULL

**eg:**添加全程阻塞

//屏蔽掉 SIGQUIT 信号

sigset_t sigSet;

sigemptyset(&sigSet);

sigaddset(&sigSet,SIGQUIT);

sigprocmask(SIG_BLOCK,&sigSet,NULL);

struct sigaction act;

act.sa_sigaction=SignHandlerNew;

act.sa_flags=SA_SIGINFO;

sigemptyset(&act.sa_mask);

sigaction(SIGINT,&act,NULL);

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

ldset 是传出参数, 存放进程原有的信号集, 通常为 NULL

**eg:**添加全程阻塞

//屏蔽掉 SIGQUIT 信号

sigset_t sigSet;

sigemptyset(&sigSet);

sigaddset(&sigSet,SIGQUIT);

sigprocmask(SIG_BLOCK,&sigSet,NULL);

struct sigaction act;

act.sa_sigaction=SignHandlerNew;

act.sa_flags=SA_SIGINFO;

sigemptyset(&act.sa_mask);

sigaction(SIGINT,&act,NULL);

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以点击这里获取!

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值