013_C标准库函数之<signal.h>

2024-04-18 15:44
文章标签 signal 标准 013 库函数

本文主要是介绍013_C标准库函数之<signal.h>,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

头文件<signal.h>中提供了一些用于处理程序运行期间所引发的异常条件的功能,如处理来源于外部的中断信号或程序执行期间出现的错误等事件。

用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?
同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中的进程捕获到这个信号然后作出一定的操作并最终被终止。

信号是UNIX和Linux系统响应某些条件而产生的一个事件,接收到该信号的进程会相应地采取一些行动。通常信号是由一个错误产生的。
但它们还可以作为进程间通信或修改行为的一种方式,明确地由一个进程发送给另一个进程。一个信号的产生叫生成,接收到一个信号叫捕获

以上是我觉得说的还不错的关于信号的诠释,当然了,如果要刨根问底的话,那这些描述就太简单了,但是我们的主要目标是使用signal函数并操作信号,关于信号产生的背景这里不做过多探讨,有兴趣的朋友可以自问度娘,下来我们直入主题:

首先,我们这里着重介绍一下signal函数

void (*signal(int sig, void (*handler)(int)))(int);

这个函数看起来非常复杂,其实剖析开看,是这样的:里面是signal(int sig, void (*handle)(int)),就是一个signal函数,第一个入参为一个int类型的sig,第二个入参为void (int)类型的函数指针(关于函数指针和指针函数不懂的,可以参考我前面的文章:000_函数指针和指针函数?-CSDN博客),其实就是准备捕获的信号的参数由sig给出,接收到的指定信号后要调用的函数由参数handle给出,接下来再看外面的函数:我们把signal看作一个整体T,外面的函数形式就是void (*T)(int);该函数返回一个与handle相同类型的指针,指向先前指定信号处理函数的函数指针(请仔细品味这句话)

注意信号处理函数的原型必须为void func(int)因为函数指针定义是void (*handle)(int);

其次,我们再看看信号表:

我们可以看到有64个信号,这里我们不一一说明,只是说一下比较常用的信号值及其含义:

SIG_ 宏与 signal 函数一起使用来定义信号的功能。

宏 & 描述
SIG_DFL
默认的信号处理程序。
SIG_ERR
表示一个信号错误。
SIG_IGN
忽视信号。

SIG 宏用于表示以下各种条件的信号码:

宏 & 描述
SIGABRT
程序异常终止。
SIGFPE
算术运算出错,如除数为 0 或溢出。
SIGILL
非法函数映象,如非法指令。
SIGINT
中断信号,如 ctrl-C。
SIGSEGV
非法访问存储器,如访问不存在的内存单元。
SIGTERM
发送给本程序的终止请求信号。

【函数1:signal 】


【格式】

void (*signal(int sig, void (*handler)(int)))(int);

【功能】

该函数设置一个函数来处理信号,即信号处理程序。

signal()用于确定以后当信号sig出现时的处理方法。如果handler的值是SIG_DFL,那么就采用实现定义的缺省行为;如果handler的值是SIG_IGN,那么就忽略该信号;否则,调用handler所指向的函数(参数为信号类型)。有效的信号包括:

SIGABRT异常终止,如调用abort()。
SIGFPE算术运算出错,如除数为0或溢出。
SIGILL非法函数映象,如非法指令。
SIGINT交互式信号,如中断。
SIGSEGV非法访问存储器,如访问不存在的内存单元。
SIGTERM发送给本程序的终止请求信号。

signal()返回信号sig原来的的handler;如果出错,则返回SIG_ERR。

当随后出现信号sig时,就中断正在执行的操作,转而执行信号处理函数(*handler)(sig)。如果从信号处理程序中返回,则从中断的位置继续执行。

信号的初始状态由实现定义。

【入参】

int sig:信号,比如SIGINT,SIGKILL等

void (*handler)(int)):函数指针原型,就是void (int)函数

【返回值】

void(*)(int);一个函数指针类型的返回值

【test_code】

直接调用:

挂钩调用:

创建类型对象调用:

以上都是调用的方法,其实都大同小异,不过我还是建议使用最后一个方法比较好一些

【总结】

signal函数的的入参就是信号,函数指针,所以可以理解此函数就是捕捉到相应的信号后,然后直接跳到函数指针处对信号进行进一步的处理,那么处理完后会不会继续回来处理程序呢?从我们的案例当中可以看到是直接结束了,因为我们捕捉的是"ctrl+c"信号:退出程序,我试了其他几个信号,也不行,捕捉到信号后,直接到信号处理函数运行,运行完后直接退出,这个到底是不继续回来处理函数?还是说就直接终止了呢?还需要探究,我尚不能给出定论,有知道的大牛可以麻烦告知我下,小弟在这里谢过了^-^

【函数2:raise 】


【格式】

int raise(int sig)

【功能】

促使生成信号 sigsig 参数与 SIG 宏兼容

【入参】

  • sig -- 要发送的信号码。下面是一些重要的标准信号常量:
信号
SIGABRT(Signal Abort) 程序异常终止。
SIGFPE(Signal Floating-Point Exception) 算术运算出错,如除数为 0 或溢出(不一定是浮点运算)。
SIGILL(Signal Illegal Instruction) 非法函数映象,如非法指令,通常是由于代码中的某个变体或者尝试执行数据导致的。
SIGINT(Signal Interrupt) 中断信号,如 ctrl-C,通常由用户生成。
SIGSEGV(Signal Segmentation Violation) 非法访问存储器,如访问不存在的内存单元。
SIGTERM(Signal Terminate) 发送给本程序的终止请求信号。

【返回值】

如果成功该函数返回零,否则返回非零

【test_code】

发送SIGINT

发送SIGTERM

【总结】

raise是发送一个信号给当前进程,需要用signal函数去捕获,然后将捕获到的信号用函数指针callfptr处理,但是,如果是终止或者异常终止等信号请求,则实际直接回终止当前进程的运行,并不会再去回调函数指针

关于信号的应用及扩展,在Linux中有大量的描述,以及sigaction等功能强大的函数,这个有兴趣的可以去看看,后面我们也会在Liunx C模块中去讲解这些,当然了,本人还是觉得先把C的这些搞清楚,因为linux C是在C的基础之上去搞的,切勿好高骛远哦,一步步来,加油,一起共勉

这篇关于013_C标准库函数之<signal.h>的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/915192

相关文章

【操作系统】信号Signal超详解|捕捉函数

🔥博客主页: 我要成为C++领域大神🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞👍收藏⭐评论✍️ 本博客致力于知识分享,与更多的人进行学习交流 ​ 如何触发信号 信号是Linux下的经典技术,一般操作系统利用信号杀死违规进程,典型进程干预手段,信号除了杀死进程外也可以挂起进程 kill -l 查看系统支持的信号

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述

气象站的种类和应用范围可以根据不同的分类标准进行详细的划分和描述。以下是从不同角度对气象站的种类和应用范围的介绍: 一、气象站的种类 根据用途和安装环境分类: 农业气象站:专为农业生产服务,监测土壤温度、湿度等参数,为农业生产提供科学依据。交通气象站:用于公路、铁路、机场等交通场所的气象监测,提供实时气象数据以支持交通运营和调度。林业气象站:监测林区风速、湿度、温度等气象要素,为林区保护和

C++标准模板库STL介绍

STL的六大组成部分 STL(Standard Template Library)是 C++ 标准库中的一个重要组成部分,提供了丰富的通用数据结构和算法,使得 C++ 编程变得更加高效和方便。STL 包括了 6 大类组件,分别是算法(Algorithm)、容器(Container)、空间分配器(Allocator)、迭代器(Iterator)、函数对象(Functor)、适配器(Adapter)

C++11 标准库头文件模拟实现

系列文章目录 文章目录 系列文章目录前言● 智能指针模板● Vector1. 简单版本2. X 总结 前言 暂不考虑支持多线程 常用STL的简单实现,主要内容百行左右完成,意在理解STL的原理 ● 智能指针模板 SharedPtr #include <assert.h>#include <atomic>template <class T>class S

SuiNS发布子名及新命名标准,推动Web3身份结构的进步

SuiNS子名是Sui Name Service的强大扩展,最近与新命名标准一起发布。子名允许用户在一个主要的SuiNS名下创建额外的自定义身份,而无需额外费用。用户 @gia 可以创建如 gaming@gia 或 lending@gia 这样的子名,从而增强个人组织和支持群组与组织的层级结构。 这一发展对于个人和企业都具有重要意义。通过子名,公司、DAO和其他组织可以为其用户或员工发放品牌账户

「Python标准库:fileinput」优雅的读取文件

每当我写个脚本涉及文件输入时,一般写法都是下面这种 import sysfile_in = sys.argv[1]for line in open(file_in, 'r'):commands 这个操作有一个缺点就是,如果我想从管道里面传入数据给Python的话,就会报错,因为原代码要求文件而不是标准输入。 这个问题可以通过Python的一个标准库: fileinput进行解决。 imp

Java中的标准注解与数据校验:深入解析与实例

目录 Java中的标准注解与数据校验:深入解析与实例1. 基础校验注解`@NonNull``@NotBlank``@Size` 2. 数值校验注解`@Min` & `@Max``@Positive` & `@Negative` 3. 枚举与模式匹配自定义注解示例(概念性展示) 4. 自定义校验逻辑结论 Java中的标准注解与数据校验:深入解析与实例 在Java开发中,注解(An

Lucene的一个简单的标准测试(Lucene包基于3.5版本的)

Lucene编程一般分为:索引、分词、搜索 索引源代码: package lucene的一个标准测试;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;

【Rust日报】2020-10-28 RustSBI项目已进入RISC-V SBI标准

RustSBI项目已进入RISC-V SBI标准 RISC-V指令集的SBI标准规定了类Unix平台下,操作系统运行环境的规范。目前,RustSBI项目已获得SBI编号4,代表它已经被收录入RISC-V SBI标准。 RISC-V架构中,存在着定义于操作系统之下的运行环境。这个运行环境不仅将引导启动RISC-V下的操作系统,还将常驻后台,为操作系统提供一系列二进制接口,以便其获取和操作硬件信息。

【Rust日报】2021-11-16 「投票」为Rust标准库添加控制台输入API

【投票】为Rust标准库添加控制台输入API Simple Console Input API for Standard Library StrawPoll.com: 我们正试图将一个简单的控制台输入API推送到标准库中,以使编写简单的命令行输入变得更容易,我们需要社区决定实现的高级程度。因为这是一个相当有争议的话题(双方的数量非常均匀),所以这次投票就是为了解决这个问题。 注意:下面的例子