所谓信号(singal),在我的理解来说,其实和单片机开发中的中断差不多,但是它并非是由系统硬件所提供的,而是软件操作系统的支持的一种提醒机制。

  收到信号之后的处理方法,一般由三种:

  (1)第一种是类似于中断处理函数,对于要处理的信号,进程指定某个处理函数。

  (2)第二种是忽略某个信号,不做任何处理。

  (3)第三种是使用系统默认的处理方式,比如Ctrl+c的终止当前进程。

  

  Linux中常用的信号有30多种,每个信号都以关键字SIG开头,比如异常终止的信号,名叫SIGABRT。

  在头文件《Singal.h》中,他们都被定义成整数。

  下面有一些常用的信号量:

  SIGALRM :使用定时器函数alarm()后,当定时时间到达时所产生的信号

  SIGINT:当用户在终端使用Ctrl+c后产生的信号(如果对这个信号不做别的重定义,那么它的意义就是终止当前进程)

  SIGKILL:这个信号是两个不能捕捉,不能忽略的信号之一,他的作用在于杀死某个进程

  SIGSTOP:这个信号是两个不能捕捉,不能忽略的信号之一,他的作用在于停止某个进程

  ……

  使用kill -l命令可以产看当前系统的所用信号量。

  

  信号如果使用在代码中,当然有对应的函数,比如函数:sigaction()这个函数就是用来重新定义,当信号产生时的处理方式……

  在单片机编程中,有点像中断回调函数的登录!

  函数sigaction函数的原形如下:

  sigaction(int signum , const struct sigaction *act, struct sigaction *oldaction)

  现在对参数进行讲解:

  int signum :指定想要修改处理方式的信号,比如SIGINT,当用户在终端输出Ctrl + c后,我们可以改变它的处理,也就是不用终止当前进程

  △正如上面所说,有两个信号的处理无法被用户改变,就是SIGKILL和SIGSTOP这两个信号,打死也改不了

  actoldact是相同类型的结构体,前者指定新的处理,后者是原来的处理方法。

  那个sigaction结构体的原形如下:

  

  void(*sa_handler)(int)是一个函数指针,用来指定信号发生后的处理函数。

  void (*sa_sigaction)(int,siginfo_t*,void*)也是用来指定信号发生后的处理函数……

  至于在信号发生后,以上两个函数选择哪一个来使用,则取决于成员sa_flags.如果sa_flags的值中包含了SA_SIGINFO时,则使用第二个函数,否则使用第一个函数。

  sa_mask成员用来指定在信号函数执行期间,需要被屏蔽的信号。

  sa_flags成员用于指定信号处理的行为,它是下值的按位或组合 。

  SA_RESTART:被信号打断的进程重启

  SA_NOCLDSTOP:父进程在子进程暂停或继续运行时,不会收到SIGCHID信号。

  解释:

  在Linux的多进程编程中,SIGCLD是一个非常重要的信号。当一个子进程退出时,并不是立即释放其占用的资源,而是通知其父进程,由父进程进行后续的工作。
  在这一过程中,系统将依次产生下列事件。
  1)向父进程发送SIGCLD信号,子进程进入zombie(僵尸)状态。
  2)父进程接收到SIGCLD信号,进行处理。

  不过,我还是对这个信号有些不明白!

  SA_NOCLDWAIT:父进程在子进程退出时,不会收到SIGCHID信号。这样子进程即使退出了,也不会形成僵尸进程

  SA_NODEFER:信号的屏蔽无效,即使在中断服务函数处理中,任然能发出这个信号

  SA_RESETHAND:在信号被处理过一次后,恢复系统本来的默认处理

  SA_SIGINFO:指定信号发生后,是使用第一个函数还是第二个函数

  ——————————————————————————————————————————————————————

  现在开始写代码,需求如下,当用户按下Ctrl+c后,系统并不会终止当前进程,而是答应出一句话,然后在按一次,这时才会终止进程。

  

#include<signal.h>
#include<stdio.h>
#include<stdlib.h> void handler(int sig)
{
printf("抓到一个Ctrl+C信号:%d.\n",sig); return;
} int main(void)
{
struct sigaction act; act.sa_handler = handler;//指定使用的信号服务函数
act.sa_flags = SA_RESETHAND;//设置信号复归模式
sigemptyset(&act.sa_mask);//清空屏蔽信号集 sigaction(SIGINT,handler,NULL);//重定义信号处理 while()
{
//等待信号发生
printf("等待信号发生中!\n");
sleep();
} return ;
}

  代码编写完毕,现在开始做makefile

  好,这个也做完了!

  现在执行编译命令!

  一大堆警告,哎!!怎么办呢!!!

  

 sigaction(SIGINT,&act,NULL);//原来是自己在这里写错了,把函数直接当成结构体了

  修改后在编译……安全通过,执行代码。

  结果如下:

  

  现在我按一下Ctrl+c,看看会发生什么。

  

  进程并没有终止,而是按照我们的要求,输出了一句话。至于那个2代表的是什么意思?我现在还不知道……如果你知道,希望能告诉我一下。

  然后我再次按下Ctrl+c,结果如下:

  

  进程果然停止了……

  当然,如果修改一下代码,将系统默认处理重设的语句屏蔽掉,那么这个进程永远也不会停止了!

  //act.sa_flags   = SA_RESETHAND;//设置信号复归模式

  …………

  现在使用另一个信号,闹钟信号来实现一个功能,既,系统在休眠后,每隔3秒打印出当前的时间。

  

#include<unistd.h>
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<time.h> void handler(int sig)
{
time_t curtime; time(&curtime);
printf("现在时间:%s\n",ctime(&curtime));
alarm();
} int main(void)
{
alarm();
signal(SIGALRM,handler);
printf("进入休眠!\n");
while()
{
sleep();
} return ;
}

代码编写完毕,执行结果如下!

  

  执行结果无误。

  当然,这只是两个简单的信号,还有别的信号等改天再试,现在都快十一点了……明天还得上班!

Linux学习笔记(10)-信号的更多相关文章

  1. APUE学习笔记——10 信号

    信号的基本概念     信号是软件中断,信号提供了解决异步时间的方法.     每一中信号都有一个名字,信号名以SIG开头. 产生信号的几种方式     很多条件可以产生信号:     终端交互:用户 ...

  2. Linux学习笔记19——信号2

    上一节中讲到了sigprocmask函数,它的作用是检查或修改它的进程信号掩码,这一节我们主要学习捕捉与忽略信号的函数sigaction和等待信号函数. 一  sigaction函数的作用 定义在接收 ...

  3. APUE学习笔记——10信号——信号接口函数 signal 和 sigaction

    signal函数     signal函数是早起Unix系统的信号接口,早期系统中提供不可靠的信号机制.在后来的分支中,部分系统使用原来的不可靠机制定义signal函数,如 Solaris 10 .而 ...

  4. Linux学习笔记18——信号1

    一 信号的基本概念 信号:是向进程发送的软件通知,通知进程有事件发生. 生成:表示一个信号的产生. 捕获:表示接收到一个信号. 信号的寿命:信号的生成和传递之间的时间间隔. 挂起的信号:已经生成但还未 ...

  5. linux学习笔记-10.解压与压缩

    1.gzip压缩 gzip a.txt 2.解压 gunzip a.txt.gzgzip -d a.txt.gz 3.bzip2压缩 bzip2 a 4.解压 bunzip2 a.bz2bzip2 - ...

  6. 小白的linux学习笔记10:安装nginx和第一个网页

    sudo yum install nginx sudo systemctl status nginx sudo systemctl start nginx 检查端口:netstat -tlpn sud ...

  7. Linux学习笔记10——文件I/O之一

    UNIX系统中的大多数文件I/O只需要用到5个函数:open,read,write,lseek以及close 文件描述符 文件描述符是一个非负整数,所有打开的文件都通过文件描述符引用 文件描述符的变化 ...

  8. Linux学习笔记10

    创建文件 touch touch filenames 创建文件夹 mkdir mkdir dir3 dir4 dir5 建立多个文件夹 mkdir ~/games  在登录用户的本目录之下建立game ...

  9. Linux学习笔记10—Linux下chkconfig命令详解

    chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 使用语法: chkconfig [--a ...

  10. APUE学习笔记——10.9 信号发送函数kill、 raise、alarm、pause

    转载注明出处:Windeal学习笔记 kil和raise kill()用来向进程或进程组发送信号 raise()用来向自身进程发送信号. #include <signal.h> int k ...

随机推荐

  1. 5种 JavaScript 调用函数的方法

    一次又一次的,我发现,那些有bug的Javascript代码是由于没有真正理解Javascript函数是如何工作而导致的(顺便说一下,许多那样的代码是我写的).JavaScript拥有函数式编程的特性 ...

  2. 没有素描色彩基础适合学习UI吗,如果可以,该怎么学?

      文章背景,来自[ UI设计交流群 - 92588284 ]的一次探讨,由于个人视野有限,个中观点有失狭隘,仅供参考,欢迎拍砖: 问题一:一个朋友想学UI设计,没有任何基础的,也没有美术功底,想问问 ...

  3. Eclispe远程调试tomcat设置

    首先在catelina.sh中添加 JAVA_OPTS="$JAVA_OPTS -Xrunjdwp:transport=dt_socket,address=23787,server=y,su ...

  4. Android之ListView性能优化——一行代码绑定数据——万能适配器

    如下图,加入现在有一个这样的需求图,你会怎么做?作为一个初学者,之前我都是直接用SimpleAdapter结合一个Item的布局来实现的,感觉这样实现起来很方便(基本上一行代码就可以实现),而且也没有 ...

  5. JDK,JRE,JVM,三者的区别于联系?

    万事开头难,从基础抓起! 下载JDK官网:http://www.oracle.com/technetwork/java/javase/downloads/index.html JDK:Java Dev ...

  6. dos命令行 指令

    盘符: 例如想进入D盘 d: ../ 上一层目录 md 文件夹名 新建文件夹cd 文件夹名 进入到该目录cd.. 返回上一层目录cd\ 返回根目录 cd \windows 进入到当前盘Windows目 ...

  7. 【转】ORACLE的REDO与UNDO

    一.什么是redo?redo:oracle在在线或者归档重做日志文件中的记录的信息,外以出现失败时可以利用这些数据来"重放"事务.每个oracle数据都至少有二个在线重做日志组,每 ...

  8. CentOS 6.5 安装 Redis-3.2.6

    到官网下载最新版的 Redis-3.2.6, 我把它放到文件夹:/usr/local/src/centos-sdk/source2/redis 安装脚本 redis-3.2.6.sh #!/bin/b ...

  9. Python购物车程序

    1.要求用户输入工资,然后打印购物菜单 2.用户可以不断的购买商品,直到钱不够为止 3.退出时格式化打印用户已购买的商品和剩余金额 salary = int(input("请输入你的工资:& ...

  10. 简单的C语言文法

    <程序>→<外部声明>|<程序><外部声明> <外部声明>→<函数定义>|<声明> <函数定义>→< ...