当前课程知识点:基于Linux的C++ >  第十三讲 进程编程 >  13.03 信号 >  LinuxCPP1303

返回《基于Linux的C++》慕课在线视频课程列表

LinuxCPP1303在线视频

LinuxCPP1303

下一节:LinuxCPP1304

返回《基于Linux的C++》慕课在线视频列表

LinuxCPP1303课程教案、知识点、字幕

接下来一个重要的概念就是信号

它是一种重要的进程间通讯机制

信号signal

是发送给进程的特殊的异步消息

当进程接收到这个信号的时候

它就会立即处理

特别注意这一点

接收到信号立即处理

这个时候它并不一定

能够完成当前函数的调用

甚至当前的代码行

不一定能够做完 就会被中断

特别注意

中断这些当前函数运行

立即处理这个信号

这是信号处理中特别重要的一点

在Linux操作系统中有很多种信号

这些信号都各有各的意义

系统以数字来标识这些信号

在程序中使用的时候

一般我们使用它的名字

对应的宏名来标记它 来使用它

系统信号

都有自己的缺省的处理例程

也就是说如果你没设

那么这个对应的信号

它就有个特定的处理的方式

缺省的处理方式

一般就是终止进程

生成内核转储文件或者忽略

这么几大类

这种典型的处理方式

如果你对它的处理方式不满意

或者达不到你的要求

你可以写你的信号处理例程

把它挂接上去就OK

我们后边会有例子给大家展示

如何处理这个问题

使用“kill –l”这个命令

可以查看操作系统所支持的信号的

全部列表

特别注意这一点 不同的操作系统

它所支持的信号可能是不一样的

要看你自己所使用的实际Linux系统是什么

才能看到它用到的信号有哪些

这是Linux系统中常用的信号的列表

包括这些信号

在我们程序中所使用到的名字

包括它们对应的值

和它们的缺省动作

和每个信号所应该具有的含义

都在这个系统信号表里面

给大家列出来了

具体的信号我就不解释了

需要的时候

我们会一个一个地去解释它

总共是31个最主要的信号

两个进程之间

可能会发送一些特定的信号

A进程给B进程发出一个信号

那么B进程就会响应这个信号

进行特定的处理

两个最重要的信号是SIGTERM、SIGKILL

一个叫终止信号 一个是杀掉信号

都是终止进程的信号

前者是请求 是terminate

我请求你停下来吧

SIGTERM 请求停止

SIGKILL 不管三七二十一

杀掉它 强制杀掉那个进程

就这个意思

这是两个最重要的终止进程信号

还有两个信号SIGUSR1、SIGUSR2

这是用户自定义的信号

我们可以用这两个信号

来做自己的处理

你想让两个进程做些特定的处理

那么你就可以向它发一个SIGUSR1信号

或者SIGUSR2信号

然后那边针对这个特定的信号

就编写一个信号处理例程

就可以处理这个特定的信号

这都是用户可以定义的

整个信号处理的过程中

当一个进程接收到信号以后

它就会根据信号特定的配置

来决定如何响应这个信号

缺省配置前面不说了嘛

在程序没有进行处理的时候

那么这个信号就会按照缺省的配置

进行去处理

如果你定义了自己的信号处理例程

那么它就不会按照缺省的

那个处理过程去对它进行处理

程序处理信号的时候

它会按照信号处理例程里面

所提供的那个函数指针

来调用它所指定的那个函数

那个函数指针型式是固定的

那么你实现这个函数

就必须是那个函数指针型式

必须按照信号处理例程的函数指针型式

定义一个信号处理函数

然后调用它

最重要的一个信号处理函数就是sigaction

它设置信号的配置

这个函数需要带signum(整型参数)

act(指向const struct sigaction的一个指针)

oldact(指向struct sigaction的一个指针)

总共三个参数

signum就是对应的信号编号

act和oldact

都是指向sigaction这个结构体的指针

前者是新的指针

后者是保存老的sigaction的指针

为什么呢

因为每一个信号对应的处理例程

它原先就有一个 有的是缺省的

有的可能是你原先设定的

现在你想为这个信号

设定一个新的处理例程

那么你就把新的处理例程

给它设置进去

但是原先的那个 你得保存起来

你可能把这个信号处理例程处理完以后

要恢复成原来那个缺省的处理模式

或者原先你设置的那个处理模式

对吧 你必须要恢复过来

所以老的那个要保存起来

这就是sigaction这三个参数的意义

这个地方有一个小讨厌

就是什么呢

这个函数sigaction的名字

和这个结构体的名字一模一样

这个结构体的名字也叫sigaction

在一开始编程的时候容易犯糊涂

这到底是函数还是结构体

其实又是函数又是结构体

所以用的时候要特别去注意这一点

为了区分它 所以在结构体前面

我总是写struct

我不会省略这个struct

哪怕我写的是C++代码

我也不省略这个struct

表示它是结构体 它不是函数

要能区分它 就这个意思

这个信号结构体特别重要

我们处理信号的时候

一定要操作的就是这个信号结构体

要非常地了解

它这里面最重要的一个成员就是sa_handler

它就用来表达这个对应的信号

它的处理的例程——那个函数指针是什么

你定义了一个信号处理例程

那么你就把这个信号处理例程

的入口地址 传给sa_handler就OK了

它的取值如果你给它SIG_DFL

就表示使用缺省那个配置

来处理这个信号

如果你给它SIF_IGN 就是忽略它

这个信号来了 就忽略它

就不理它 OK

否则就是你自己定义的

那个信号处理例程的函数入口地址

那就是一个函数指针了

但同学们要特别记住

因为早期Linux在实现的时候

没有C++ 它用的是C代码

所以这个信号处理例程

这个函数是C函数

你写C++代码的时候要特别小心

传的是一个C函数的一个函数指针

不是C++的函数

更不是类的成员函数

这一点是需要注意的

在处理信号的时候要特别注意

一 信号是一个异步操作

所以当你处理这个信号的时候

主程序本身是非常非常脆弱的

信号处理例程本身应该尽可能得短

不能太长了 太长的话

它非常容易导致整个程序错误

包括导致我们的信号处理的过程中

就会被中断

那你这个信号就没有被正确处理

这肯定不行

所以信号处理例程应该尽可能得短小

尽量不要在信号处理例程中进行I/O操作

因为I/O操作在很多情况下

它是长而复杂的

在信号处理例程里边

处理复杂的I/O操作

很多时候都有可能导致问题

所以特别注意这一条

尽量不要在信号处理例程中

实施I/O操作

在信号处理例程中

进行复杂的赋值操作

理论上也是不应该的

信号处理例程本身

它可能不是一个原子操作

什么意思

就是说它本身是可能会被中断的

所以如果进行一个复杂的赋值

它就有可能导致我们赋值了一部分

然后它被中断

然后剩下一部分数据就没有被赋值

没有意义

这个数据的一致性

我就没有办法保证

正是在这一点上

在信号处理例程里面

为了对量进行赋值

它有一个特殊的规定

就是一般情况下应该使用这个型式

来定义全局量

然后赋值那个全局量

它等价于一个int

也就是说在信号处理例程里边

你赋值一个整型是OK的

赋值一个指针

不管是32位指针 还是64位指针

实际上也是OK的

但是更大一点的数据尺寸

就需要特别地小心

你必须保证那个处理的过程中

不会被中断 否则就是有问题的

这一点在处理信号的时候

是需要特别注意的

我们来看一段代码

我们定义sigusr1_count

把它初始化成0

定义一个外部C函数void OnSigUsr1()

这个信号处理例程

这是一个简单的信号处理例程

然后在我们的主函数内

我们定义struct sigaction结构体的

一个变量sa

我们调用memset() 就是memory set

就设置它的内存

把它的内存全部清0 就这个意思

然后设它的sa_handler

把它设成我们的OnSigUsr1的入口地址

这个就设定了

sigaction()的基本函数处理例程

它的信号处理例程就被你设定好了

然后你调用sigaction()这个函数

把sa 把它挂到SigUsr1这个信号上

只要完成sigaction()这个函数调用

我们的信号处理例程OnSigUsr1()这个函数

就会被挂接在SIGUSR1这个信号上

这是完成这个信号处理的挂接

当你在程序运行的过程中

触发了一个SIGUSR1信号之后

这个信号处理例程就会被调用

比如讲我们这个程序一编译

然后你在终端里输入“kill –s SIGUSR1 pid”

这个pid就是这个程序

在运行的时候

它那个对应的进程ID,PID

向这个进程发一个SIGUSR1的信号

那么它就会执行这个信号处理例程

把sigusr1_count递增1

你就能够看到它递增后的结果

注意这一点

实现的方式就是这个模样

基于Linux的C++课程列表:

第一讲 C/C++基本语法元素

-1.1 提纲

--LinuxCPP0101

-1.2 程序设计的基本概念

--LinuxCPP0102

-1.3 简单C/C++程序介绍

--LinuxCPP0103

-1.4 程序设计的基本流程

--LinuxCPP0104

-1.5 基本语法元素

--LinuxCPP0105

-1.6 程序设计风格

--LinuxCPP0106

-1.7 编程实践

--LinuxCPP0107

-第一讲 C/C++基本语法元素--编程实践提交入口

第二讲 程序控制结构

-2.1 提纲

--LinuxCPP0201

-2.2 结构化程序设计基础

--LinuxCPP0202

-2.3 布尔数据

--LinuxCPP0203

-2.4 分支结构

--LinuxCPP0204

-2.5 break语句

--LinuxCPP0205

-2.6 循环结构

--LinuxCPP0206

-2.7 编程实践

--LinuxCPP0207

-第二讲 程序控制结构--编程实践提交入口

第三讲 函数

-3.1 提纲

--LinuxCPP0301

-3.2 函数声明、调用与定义

--LinuxCPP0302

-3.3 函数调用栈框架

--LinuxCPP0303

-3.4 编程实践

--LinuxCPP0304

-第三讲 函数--编程实践提交入口

第四讲 算法

-4.1 提纲

--LinuxCPP0401

-4.2 算法概念与特征

--LinuxCPP0402

-4.3 算法描述

--LinuxCPP0403

-4.4 算法设计与实现

--LinuxCPP0404

-4.5 递归算法(一)

--LinuxCPP0405

-4.6 递归算法(二)

--LinuxCPP0406

-4.7 容错与计算复杂度

--LinuxCPP0407

-4.8 编程实践

--LinuxCPP0408

-第四讲 算法--编程实践提交入口

第五讲 程序组织与开发方法

-5.1 提纲

--LinuxCPP0501

-5.2 库与接口

--LinuxCPP0502

-5.3 随机数库(一)

--LinuxCPP0503

-5.4 随机数库(二)

--LinuxCPP0504

-5.5 作用域与生存期

--LinuxCPP0505

-5.6 典型软件开发流程(一)

--LinuxCPP0506

-5.7 典型软件开发流程(二)

--LinuxCPP0507

-5.8 编程实践

--LinuxCPP0508

-第五讲 程序组织与开发方法--编程实践提交入口

第六讲 复合数据类型

-6.1 提纲

--LinuxCPP0601

-6.2 字符

--LinuxCPP0602

-6.3 数组(一)

--LinuxCPP0603

-6.4 数组(二)

--LinuxCPP0604

-6.5 结构体

--LinuxCPP0605

-6.6 编程实践

--LinuxCPP0606

-第六讲 复合数据类型--编程实践提交入口

第七讲 指针与引用

-7.1 提纲

--LinuxCPP0701

-7.2 指针基本概念

--LinuxCPP0702

-7.3 指针与函数

--LinuxCPP0703

-7.4 指针与复合数据类型(一)

--LinuxCPP0704

-7.5 指针与复合数据类型(二)

--LinuxCPP0705

-7.6 字符串

--LinuxCPP0706

-7.7 动态存储管理(一)

--LinuxCPP0707

-7.8 动态存储管理(二)

--LinuxCPP0708

-7.9 引用

--LinuxCPP0709

-7.10 编程实践

--LinuxCPP0710

-第七讲 指针与引用--编程实践提交入口

第八讲 链表与程序抽象

-8.1 提纲

--LinuxCPP0801

-8.2 数据抽象(一)

--LinuxCPP0802

-8.3 数据抽象(二)

--LinuxCPP0803

-8.4 链表(一)

--LinuxCPP0804

-8.5 链表(二)

--LinuxCPP0805

-8.6 链表(三)

--LinuxCPP0806

-8.7 链表(四)

--LinuxCPP0807

-8.8 函数指针(一)

--LinuxCPP0808

-8.9 函数指针(二)

--LinuxCPP0809

-8.10 抽象链表(一)

--LinuxCPP0810

-8.11 抽象链表(二)

--LinuxCPP0811

-8.12 编程实践

--LinuxCPP0812

-第八讲 链表与程序抽象--编程实践提交入口

第九讲 类与对象

-9.1 提纲

--LinuxCPP0901

-9.2 程序抽象与面向对象

--LinuxCPP0902

-9.3 类类型

--LinuxCPP0903

-9.4 对象(一)

--LinuxCPP0904

-9.5 对象(二)

--LinuxCPP0905

-9.6 类与对象的成员(一)

--LinuxCPP0906

-9.7 类与对象的成员(二)

--LinuxCPP0907

-9.8 类与对象的成员(三)

--LinuxCPP0908

-9.9 继承(一)

--LinuxCPP0909

-9.10 继承(二)

--LinuxCPP0910

-9.11 继承(三)

--LinuxCPP0911

-9.12 多态(一)

--LinuxCPP0912

-9.13 多态(二)

--LinuxCPP0913

-9.14 编程实践

--LinuxCPP0914

-第九讲 类与对象--编程实践提交入口

第十讲 操作符重载

-10.1 提纲

--LinuxCPP1001

-10.2 四则运算符重载(一)

--LinuxCPP1002

-10.3 四则运算符重载(二)

--LinuxCPP1003

-10.4 关系与下标操作符重载

--LinuxCPP1004

-10.5 赋值操作符重载(一)

--LinuxCPP1005

-10.6 赋值操作符重载(二)

--LinuxCPP1006

-10.7 赋值操作符重载(三)

--LinuxCPP1007

-10.8 赋值操作符重载(四)

--LinuxCPP1008

-10.9 赋值操作符重载(五)

--LinuxCPP1009

-10.10 流操作符重载(一)

--LinuxCPP1010

-10.11 流操作符重载(二)

--LinuxCPP1011

-10.12 流操作符重载(三)

--LinuxCPP1012

-10.13 操作符重载总结

--LinuxCPP1013

-10.14 编程实践

--LinuxCPP1014

-第十讲 操作符重载--编程实践提交入口

第十一讲 泛型编程

-11.1 提纲

--LinuxCPP1101

-11.2 泛型编程概览

--LinuxCPP1102

-11.3 异常处理机制(一)

--LinuxCPP1103

-11.4 异常处理机制(二)

--LinuxCPP1104

-11.5 运行期型式信息(一)

--LinuxCPP1105

-11.6 运行期型式信息(二)

--LinuxCPP1106

-11.7 模板与型式参数化

--LinuxCPP1107

-11.8 题外话:术语翻译

--LinuxCPP1108

-11.9 泛型编程实践(一)

--LinuxCPP1109

-11.10 泛型编程实践(二)

--LinuxCPP1110

-11.11 泛型编程实践(三)

--LinuxCPP1111

-11.12 泛型编程实践(四)

--LinuxCPP1112

-11.13 泛型编程实践(五)

--LinuxCPP1113

-11.14 泛型编程实践(六)

--LinuxCPP1114

-11.15 泛型编程实践(七)

--LinuxCPP1115

-11.16 泛型编程实践(八)

--LinuxCPP1116

-11.17 泛型编程实践(九)

--LinuxCPP1117

-11.18 泛型编程实践(十)

--LinuxCPP1118

-11.19 编程实践

--LinuxCPP1119

-第十一讲 泛型编程--编程实践提交入口

第十二讲 Linux系统编程基础

-12.1 提纲

--LinuxCPP1201

-12.2 程序执行环境(一)

--LinuxCPP1202

-12.3 程序执行环境(二)

--LinuxCPP1203

-12.4 程序执行环境(三)

--LinuxCPP1204

-12.5 程序执行环境(四)

--LinuxCPP1205

-12.6 输入输出(一)

--LinuxCPP1206

-12.7 输入输出(二)

--LinuxCPP1207

-12.8 文件系统

--LinuxCPP1208

-12.9 设备

--LinuxCPP1209

-12.10 库(一)

--LinuxCPP1210

-12.11 库(二)

--LinuxCPP1211

-12.12 makefile文件(一)

--LinuxCPP1212

-12.13 makefile文件(二)

--LinuxCPP1213

-12.14 makefile文件(三)

--LinuxCPP1214

-12.15 编程实践

--LinuxCPP1215

-第十二讲 Linux系统编程基础--编程实践提交入口

第十三讲 进程编程

-13.01 提纲

--LinuxCPP1301

-13.02 进程基本概念

--LinuxCPP1302

-13.03 信号

--LinuxCPP1303

-13.04 进程管理(一)

--LinuxCPP1304

-13.05 进程管理(二)

--LinuxCPP1305

-13.06 进程管理(三)

--LinuxCPP1306

-13.07 进程间通信(一)

--LinuxCPP1307

-13.08 进程间通信(二)

--LinuxCPP1308

-13.09 进程间通信(三)

--LinuxCPP1309

-13.10 进程间通信(四)

--LinuxCPP1310

-13.11 进程池

--LinuxCPP1311

-13.12 编程实践

--LinuxCPP1312

-第十三讲 进程编程--编程实践提交入口

第十四讲 线程编程

-14.1 提纲

--LinuxCPP1401

-14.2 线程基本概念

--LinuxCPP1402

-14.3 线程管理(一)

--LinuxCPP1403

-14.4 线程管理(二)

--LinuxCPP1404

-14.5 线程管理(三)

--LinuxCPP1405

-14.6 线程管理(四)

--LinuxCPP1406

-14.7 线程同步机制(一)

--LinuxCPP1407

-14.8 线程同步机制(二)

--LinuxCPP1408

-14.9 C++11线程库(一)

--LinuxCPP1409

-14.10 C++11线程库(二)

--LinuxCPP1410

-14.11 C++11线程库(三)

--LinuxCPP1411

-14.12 C++11线程库(四)

--LinuxCPP1412

-14.13 C++11线程库(五)

--LinuxCPP1413

-14.14 编程实践

--LinuxCPP1414

-第十四讲 线程编程--编程实践提交入口

第十五讲 网络编程

-15.1 提纲

--LinuxCPP1501

-15.2 Internet网络协议

--LinuxCPP1502

-15.3 套接字(一)

--LinuxCPP1503

-15.4 套接字(二)

--LinuxCPP1504

-15.5 编程实践

--LinuxCPP1505

-第十五讲 网络编程--编程实践提交入口

课程文档

-课程PDF文件

LinuxCPP1303笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。