Linux fd 系列|信号编程(signal)竟能这样做?涨姿势

Linux fd 系列|信号编程(signal)竟能这样做?涨姿势,第1张

来源 | 奇点云存储(id : qiyacloud)授权转载

如若转载请联系原公众号

信号是什么?

首先说,信号(signal)是什么?

信号( signal )本质是 Linux 进程间通信的一种机制,也叫 软中断信号 。既然是通信机制,那么就是传递信息用的,信号传递的信息很简单,就是一个整数,一般用于配合系统管理任务,比如进程的终结、恢复、热加载等。

信号都用整数常量表示,命名以 SIG 为前缀,比如 SIGINT( ctrl-c 触发),SIGKILL( kill -9 触发 )。

信号一般怎么产生?

信号处理分为两个阶段

signalfd 是什么?

了解了什么是信号( signal ),那 signalfd 又会是什么呢?

是一个跟信号关联的 文件描述符 ,能够以 io 的行为获取到系统信号,属性上来讲 signalfd 也是一个匿名 fd 类型。

signalfd 长什么样子?

奇点按照 man signalfd 里面的例子,写了个 demo,跑在 Linux 机器上,按照惯例去看下 fd 的样子。

从这里可以得到简单的信息:

signalfd 使用姿势?

其实信号是很讲究的,甚至有信号编程一说,Linux 的 signalfd 为信号的处理提供了一种新的方法, 统一到文件的 io 模式,契合一切接文件的理念

系统调用:

该系统调用返回一个整数类型 signalfd,这个句柄跟信号行为绑定,当发生信号的时候,句柄触发可读事件。

第一个参数也可以传入一个有效的信号 fd 的句柄, 如果传入的是 -1 ,那么内核会自动创建一个新的 fd 。

完整的代码例子,在 Linux 机器上,通过 man signalfd 就可以获取到。

上面的例子,signalfd 没有信号(没有可读事件)的时候会阻塞在 read 调用上,运行效果如下:

可以看到每一次 ctrl + c 触发的信号被捕捉到,并且打印出来。用文件 io 的方式来接收信号,牛。

怎么做到的呢?照例,我们浅析一下内核的代码,位于 fs/signalfd.c ,这是一个很小的文件,正是这个文件完成了对信号“文件化”的封装。

上面最笑神重要的两个调用:

signalfd 原理剖析

1 signalfd

看一下 signalfd 支持的接口调用:

通过这个可以知道 signalfd 支持的特性:

2 signalfd_poll

这个函数做的事情非常简单,就是把 等待对象 挂到当前进程的信号结构的链表上。表头是: current->sighand->signalfd_wqh ,这个就有意思了,这里直接挂到当前进程的结构上。换句话说,唤醒也是自此表头开始。

回忆一下 timerfd ,是挂在 timerfd_ctx->wqh 的字段上。这里的差别是因为信号是对进程来说的。

3 signalfd_read

读一个 signalfd 的 *** 作非常简单,主要逻辑:碰仿亏

简要的代码注释如下:

这里就能非常清晰的看到, 进程有信号的时候,signalfd 句柄就是可读的大州

signal 和 epoll 的配合

1 熟悉的 epoll_ctl

epoll_ctl 注册 signalfd 的时候,调用 signalfd_poll , signalfd_poll 会把 epoll 创建的 wait entry 挂到 current->sighand 上。唤醒的时候调用这个 wait 链表的回调。

2 什么时候唤醒呢?

唤醒的 *** 作其实不在 signalfd.c 文件中,而是在原有的信号软中断的流程中。

为了知识的完整性,说个点, signalfd_notify 其实在 timer 定时器的流程中也有调用,但跟我们本次主干没啥关系,这里忽略。

信号的发送唤醒的简要示意图:

所有的信号发送都会调用到 send_signal ,在这个里面实现了唤醒 sighand->signalfd_wqh 链表的 *** 作。从而使得 epoll 感知到 signalfd 可读了(因为来信号了),使得 epoll 从 epoll_wait 出唤醒,然后调用 read *** 作,把信号的相关信息从句柄中读出来。

划重点:唤醒在 信号发送 的过程。

总结

我的oppo也中了signal病毒,不过我瞎猫碰上死耗子给弄掉了。大家可以试一下:(1)百度搜索oppo刷机包,会出现“Coloros社区,oppo手机系统论坛”,点进去就进入了固件下载界面,找到自己的机型,态贺里面会有一个“立即下载”和“刷机教程”按钮,点击立即下载(下载完了之后那个“立即下载”可能会变成“立即安装”,不用点它),下载期间你可以看看刷机教程。(2)你去文件夹-压缩包找到当天下载的比较大的zip压缩包(你也可以把排序方式换成按时间排序,那第一个就是啦),将它移动到根目录(就是不要放在任何一个文件夹里面,放在文件初始目录)。然后你就可以刷机了。(3)你可以根据刷机教程刷机,我说一下我刷机的过程:①提前备份好自己的东西(我刷完帆喊派机发现其实啥资料都没删,和恢复出渗档厂设置完全不一样),②关机,③同时点击开机键和下音量键,④点击简体中文,⑤点击安装程序,点一下自己文件里的那个安装包,确认安装,大约等个几分钟吧,⑥完了之后会出现重启按钮,点重启就可以了。

字符处理函数 \x0d\x0a本类别函数用于对单个字符进行处理,包括字符的类别测试和字符的大小写转换 \x0d\x0a\x0d\x0a头文件 ctype.h \x0d\x0a\x0d\x0a函数列表 \x0d\x0a函数类别 函数用途 详细说明 \x0d\x0a字符测试 是否字母和数字 isalnum \x0d\x0a是否字母 isalpha \x0d\x0a是猜扰亮否控制字符 iscntrl \x0d\x0a是否数字 isdigit \x0d\x0a是否可显示字符(除空格外) isgraph \x0d\x0a是否可显示字符(包括空格) isprint \x0d\x0a是否既不是空格,又不是字母和数字的可显示字符 ispunct \x0d\x0a是否空格 isspace \x0d\x0a是否大写字母 isupper \x0d\x0a是否16进制数字(0-9,A-F)字符 isxdigit \x0d\x0a字符大小写转换函数 转换为大写字母 toupper \x0d\x0a转换为小写字母 tolower \x0d\x0a\x0d\x0a地区化 \x0d\x0a本类别的函数用于处理不同国家的语言差异。 \x0d\x0a\x0d\x0a头文件 local.h \x0d\x0a\x0d\x0a函数列表 \x0d\x0a函数类别 函数用途 详细说明 \x0d\x0a地区控制 地区设置 setlocale \x0d\x0a数字格式约定查询 国家的货币、日期、时间等的格式转换 localeconv \x0d\x0a\x0d\x0a数学函数 \x0d\x0a本分类给出了各种数学计算函数,必须提醒的是ANSI C标准中的数据格式并不符合IEEE754标准,一些C语言编译器却遵循IEEE754(例如frinklin C51) \x0d\x0a\x0d\x0a头文件 math.h \x0d\x0a\x0d\x0a函数列表 \x0d\x0a函数类别 函数用途 详细说明 \x0d\x0a错误条件处理 定义域错误(函数的输入参数值不在规定的范围内) \x0d\x0a值域错误(函数的返回值不在规定的范围内) \x0d\x0a三角函数 反余弦 acos \x0d\x0a反正弦 asin \x0d\x0a反正切 atan \x0d\x0a反正切2 atan2 \x0d\x0a余弦 cos \x0d\x0a正弦 sin \x0d\x0a正切 tan \x0d\x0a双曲函数 双曲余弦 cosh \x0d\x0a双曲正弦 sinh \x0d\x0a双曲正切 tanh \x0d\x0a指数和对数 指数函数 exp \x0d\x0a指数分解函数 frexp \x0d\x0a乘积指数函数 fdexp \x0d\x0a自然对数 log \x0d\x0a以10为底的对数 log10 \x0d\x0a浮点数分解函数 modf \x0d\x0a幂函数 幂函数 pow \x0d\x0a平方根函数 sqrt \x0d\x0a整数截断,绝对值李行和求余数函数 求下限接近整数 ceil \x0d\x0a绝对值 fabs \x0d\x0a求上限接近整数 floor \x0d\x0a求余数 fmod \x0d\x0a\x0d\x0a本分类函数用于实现在不同底函数之间直接跳转代码。 头文件 setjmp.h io.h \x0d\x0a\x0d\x0a函数列表 \x0d\x0a函数类别 函数用途 详细说明 \x0d\x0a保存调用环境 setjmp \x0d\x0a恢复调用环境 longjmp \x0d\x0a\x0d\x0a信号处理 \x0d\x0a该分类函数用于处理那些在程序执行过程中发生例外的情况。 \x0d\x0a\x0d\x0a头文件 signal.h \x0d\x0a\x0d\x0a函数列表 \x0d\x0a函数类别 函数穗宽用途 详细说明 \x0d\x0a指定信号处理函数 signal \x0d\x0a发送信号 raise \x0d\x0a\x0d\x0a可变参数处理 \x0d\x0a本类函数用于实现诸如printf,scanf等参数数量可变底函数。 \x0d\x0a\x0d\x0a头文件 stdarg.h \x0d\x0a\x0d\x0a函数列表 \x0d\x0a函数类别 函数用途 详细说明 \x0d\x0a可变参数访问宏 可变参数开始宏 va_start \x0d\x0a可变参数结束宏 va_end \x0d\x0a可变参数访问宏 访问下一个可变参数宏 va_arg \x0d\x0a\x0d\x0a输入输出函数 \x0d\x0a该分类用于处理包括文件、控制台等各种输入输出设备,各种函数以“流”的方式实现 \x0d\x0a\x0d\x0a头文件 stdio.h \x0d\x0a\x0d\x0a函数列表 \x0d\x0a函数类别 函数用途 详细说明 \x0d\x0a文件 *** 作 \x0d\x0a删除文件 remove \x0d\x0a修改文件名称 rename \x0d\x0a生成临时文件名称 tmpfile \x0d\x0a得到临时文件路径 tmpnam \x0d\x0a文件访问 关闭文件 fclose \x0d\x0a刷新缓冲区 fflush \x0d\x0a打开文件 fopen \x0d\x0a将已存在的流指针和新文件连接 freopen \x0d\x0a设置磁盘缓冲区 setbuf \x0d\x0a设置磁盘缓冲区 setvbuf \x0d\x0a格式化输入与输出函数 格式输出 fprintf \x0d\x0a格式输入 fscanf \x0d\x0a格式输出(控制台) printf \x0d\x0a格式输入(控制台) scanf \x0d\x0a格式输出到缓冲区 sprintf \x0d\x0a从缓冲区中按格式输入 sscanf \x0d\x0a格式化输出 vfprintf \x0d\x0a格式化输出 vprintf \x0d\x0a格式化输出 vsprintf \x0d\x0a字符输入输出函数 输入一个字符 fgetc \x0d\x0a字符串输入 fgets \x0d\x0a字符输出 fputc \x0d\x0a字符串输出 fputs \x0d\x0a字符输入(控制台) getc \x0d\x0a字符输入(控制台) getchar \x0d\x0a字符串输入(控制台) gets \x0d\x0a字符输出(控制台) putc \x0d\x0a字符输出(控制台) putchar \x0d\x0a字符串输出(控制台) puts \x0d\x0a字符输出到流的头部 ungetc \x0d\x0a直接输入输出 直接流读 *** 作 fread \x0d\x0a直接流写 *** 作 fwrite \x0d\x0a文件定位函数 得到文件位置 fgetpos \x0d\x0a文件位置移动 fseek \x0d\x0a文件位置设置 fsetpos \x0d\x0a得到文件位置 ftell \x0d\x0a文件位置复零位 remind \x0d\x0a错误处理函数 错误清除 clearerr \x0d\x0a文件结尾判断 feof \x0d\x0a文件错误检测 ferror \x0d\x0a得到错误提示字符串 perror \x0d\x0a\x0d\x0a实用工具函数 \x0d\x0a本分类给出了一些函数无法按以上分类,但又是编程所必须要的。 \x0d\x0a\x0d\x0a头文件 stdlib.h \x0d\x0a\x0d\x0a函数列表 \x0d\x0a函数类别 函数用途 详细说明 \x0d\x0a字符串转换函数 字符串转换为整数 atoi \x0d\x0a字符串转换为长整数 atol \x0d\x0a字符串转换为浮点数 strtod \x0d\x0a字符串转换为长整数 strtol \x0d\x0a字符串转换为无符号长整型 strtoul \x0d\x0a伪随机序列产生函数 产生随机数 rand \x0d\x0a设置随机函数的起动数值 srand \x0d\x0a存储管理函数 分配存储器 calloc \x0d\x0a释放存储器 free \x0d\x0a存储器分配 malloc \x0d\x0a重新分配存储器 realloc \x0d\x0a环境通信 中止程序 abort \x0d\x0a退出程序执行,并清除环境变量 atexit \x0d\x0a退出程序执行 exit \x0d\x0a读取环境参数 getenv \x0d\x0a程序挂起,临时执行一个其他程序 system \x0d\x0a搜索和排序工具 二分查找(数据必须已排序) bsearch \x0d\x0a快速排序 qsort \x0d\x0a整数运算函数 求绝对值 abs \x0d\x0adiv \x0d\x0a得到除法运算底商和余数 \x0d\x0a求长整形底绝对值 labs \x0d\x0a求长整形除法的商和余数 ldiv \x0d\x0a多字节字符函数 得到多字节字符的字节数 mblen \x0d\x0a得到多字节字符的字节数 mbtowc \x0d\x0a多字节字符转换 wctomb \x0d\x0a多字节字符的字符串 *** 作 将多字节串转换为整数数组 mbstowcs \x0d\x0a将多字节串转换为字符数组 mcstowbs \x0d\x0a\x0d\x0a字符串处理 \x0d\x0a本分类的函数用于对字符串进行合并、比较等 *** 作 \x0d\x0a\x0d\x0a头文件 string.h \x0d\x0a\x0d\x0a函数列表 \x0d\x0a函数类别 函数用途 详细说明 \x0d\x0a字符串拷贝 块拷贝(目的和源存储区不可重叠) memcpy \x0d\x0a块拷贝(目的和源存储区可重叠) memmove \x0d\x0a串拷贝 strcpy \x0d\x0a按长度的串拷贝 strncpy \x0d\x0a字符串连接函数 串连接 strcat \x0d\x0a按长度连接字符串 strncat \x0d\x0a串比较函数 块比较 memcmp \x0d\x0a字符串比较 strcmp \x0d\x0a字符串比较(用于非英文字符) strcoll \x0d\x0a按长度对字符串比较 strncmp \x0d\x0a字符串转换 strxfrm \x0d\x0a字符与字符串查找 字符查找 memchr \x0d\x0a字符查找 strchr \x0d\x0a字符串查找 strcspn \x0d\x0a字符串查找 strpbrk \x0d\x0a字符串查找 strspn \x0d\x0a字符串查找 strstr \x0d\x0a字符串分解 strtok \x0d\x0a杂类函数 字符串设置 memset \x0d\x0a错误字符串映射 strerror \x0d\x0a求字符串长度 strlen \x0d\x0a\x0d\x0a日期和时间函数 \x0d\x0a本类别给出时间和日期处理函数 \x0d\x0a\x0d\x0a头文件 time.h \x0d\x0a\x0d\x0a函数列表 \x0d\x0a函数类别 函数用途 详细说明 \x0d\x0a时间 *** 作函数 得到处理器时间 clock \x0d\x0a得到时间差 difftime \x0d\x0a设置时间 mktime \x0d\x0a得到时间 time \x0d\x0a时间转换函数 得到以ASCII码表示的时间 asctime \x0d\x0a得到字符串表示的时间 ctime \x0d\x0a得到指定格式的时间 strftime \x0d\x0a\x0d\x0a函数库未来的发展方向 \x0d\x0a本部分用于说明各类别函数库在将来如何发展。 \x0d\x0a\x0d\x0a序号 库类别 头文件 详细说明 \x0d\x0a1 错误处理 errno.h \x0d\x0a2 字符处理 ctype.h \x0d\x0a3 地区化 local.h \x0d\x0a4 数学函数 math.h \x0d\x0a5 信号处理 signal.h \x0d\x0a6 输入输出 stdio.h \x0d\x0a7 实用工具程序 stdlib.h \x0d\x0a8 字符串处理 string.h


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/12293428.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存