信号

   信号是Unix和Linux系统响应某些条件而产生的一个条件。接收到该信号的进程会相应的采取一些行动。

   信号是由于某些错误条件而生成的,如内存冲突,浮点处理器错误或非法指令等。它们由shell和终端处理器生成来引起中断,他们还可以作为在进程间传递消息的或修改行为的一种方式,

明确地由一个进程发送给另一个进程。无论何种情况,它们的的编程接口都是相同的。信号可以被生成、捕获、响应或忽略。

       信号的名称是在头文件signed.h定义的。它们以SIG开头。

在键盘上敲入中断字符(Ctrl+C 组合键)就会向前台进程(即现在在运行的的程序)发送SIGINT(终端中断)信号,这将引起该程序的终止,除非它事先安排捕获这个信号。

  命令行实现:

    如果想发送一个信号给进程,而该进程不是当前的前台进程,就需要使用kill命令。

例如 要向运行在另一个终端的PID为512的进程发送“挂断”信号,可以使用如下命令:

kill  -HUP 512

    ps:SIGHUP   连接挂断

信号有关程序:

1.捕获信号

程序可以使用signal库函数来处理信号,

#include <signal.h>

void (*signal(ing sig, void (*func)(int)))(int);

两个参数:

   sig :准备捕获或忽略的信号量

func:收到指定的信号量后要调用的函数。可以使用两个特殊值之一来代替信号量处理函数。

SIG_IGN  忽略信号

SIG_DFL 恢复默认行为

下面的示例程序将完成以下功能:当第一次敲下Ctrl+C时做出约定的反应,第二次敲下Ctrl+C时退出。

#include<stdio.h>
#include<signal.h>
void deal(int sig)
{
printf("i get a sinal is %d",sig);
(void)signal(SIGINT, SIG_DFL);
}
int main()
{
(void)signal(SIGINT,deal);
while()
{
printf("hello world!\n");
sleep();
} }

  运行效果:

     

  分析:当用户第一次输入Ctrl+C时,函数deal会被调用,输出一条信息,然后把信号SIGINT的处理方式恢复为默认状态。第二次输入Ctrl+C的时候就会终止程序运行。

     main函数的作用是截获Ctrl+C组合键产生的SIGINT函数。没有信号出现时,它会在一个无限循环中每隔一秒打印一条消息。

  2.发送信号

  进程可以通过调用kill函数向包括它本身在内的其它进程发送一个信号。如果程序没有发送该信号的权限,对kill函数的调用功能就将失败。

   失败的常见原因是目标进程由另外一个用户所拥有。这个函数和同名的shell命令完成同样的功能,定义如下:

#include <sys/types.h>

  #include <signal.h>

int kill (pid_t, int sig)

kill函数把参数sig给定的信号量发送给由参数pid_t给出的进程号所指定的进程,成功时返回0。kill调用会在失败时返回-1并设置errno变量。失败的原因可能是:

  给定的信号无效(errno设置为EINVAL),发送进程权限不够(errno设置为EPERM),目标进程不存在(errno设置为ESRCH)。

 要想发送一个信号,发送进程必须拥有相应的权限。这通常意味着两个进程必须拥有相同的用户ID(即你只能发送信号给属于自己的进程,但超级用户可以发送信号给任何进程)。

示例代码如下:

#include<sys/types.h>
#include<signal.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h> static int alarm_stat = ; void ding (int sig)
{
printf("the sig is %d\n",sig);
alarm_stat = ;
}
int main()
{
pid_t pid;
printf("the alarm program starting!\n"); pid=fork();
switch(pid)
{
case -:
perror("fork failed");
exit();
case :
sleep();
kill(getppid(),SIGALRM);
exit();
} printf("this is parent!\n");
(void)signal(SIGALRM,ding);
pause();
if(alarm_stat)
{
printf("Ding!!!!\n");
}
printf("Done!\n");
exit();
}

  执行效果:

  

  程序分析如下:

新函数 pause() 作用 把程序的执行挂起知道有一个信号出现为止。当程序接收到一个信号时,预设好的信号处理函数将开始运行,程序也恢复正常的执行。

该函数通过fork调动启动新的进程。这个子进程休眠5S后向它的父进程发送一个SIGALRM信号。父进程在安排好捕获SIGALRM信号后暂停运行,直道接收到一个信号为止,通过在信号处理函数中

  设置标志,然后在main函数中检查标志来完成消息的输出。

 

  程序中使用信号将带来一个特殊的问题:“如果信号出现在系统调用的执行过程中会发生什么情况?” 答案是 视情况而定。

     在编写程序中处理信号的部分的代码时候必须非常小心,因为在使用信号的程序中会出现各种各用的“竞态条件”,例如如果

     调用pause函数来等待一个信号,可信号却出现在调用pause之前,就会使程序无限期的等待一个不会发生的事件。

以上内容来自《Linux程序设计第四版》

Linux学习4-信号的更多相关文章

  1. linux 学习干货

    学习了第七章. 每一个键盘对应一个信号.主要的有: ^代表 Ctrl <Backspance> erase ,删除一个字符. ^W werase,删除一个单词 ^U / ^X kill , ...

  2. Linux学习笔记14——使用fcntl实现文件锁定

    期末考试快要来了,Linux学习进度一下拉下来许多.今天学习的是文件锁定,在Linux中,实现文件锁定的方法很多,例如fcntl和lockf.下面主要是fcntl的调用. fcntl函数的原型是:in ...

  3. Linux学习--进程概念

    >>进程 说进程,感觉好空洞,来一张图,Linux下的进程: ps -eo pid,comm,cmd 说明:-e表示列出全部进程,-o pid,comm,cmd表示我们需要PID,COMM ...

  4. 2019/4/17 Linux学习

    一.Linux的文件系统 其中/prov./srv./sys 文件为文件系统,技术不过硬不要去修改:二.关于Xshell.Xft1.服务器的端口可有65535个可设置,开的越多安全性越差:2.远程登录 ...

  5. Linux学习之进程管理(十九)

    Linux学习之进程管理 进程查看 查看系统中所有进程,使用BSD操作系统的格式 语法:ps aux 选项: a:显示所有前台进程 x:显示所有后台进程 u:显示这个进程是由哪个用户产生的 语法:ps ...

  6. Linux学习-计算机基础

    Linux 学习-计算机基础 一.描述计算机的组成及其功能. 计算机系统是由硬件(Hardware)和软件(Software )两部分组成. 硬件: 从硬件基本结构上来讲,计算机是由运算器.控制器.存 ...

  7. Linux学习笔记(六) 进程管理

    1.进程基础 当输入一个命令时,shell 会同时启动一个进程,这种任务与进程分离的方式是 Linux 系统上重要的概念 每个执行的任务都称为进程,在每个进程启动时,系统都会给它指定一个唯一的 ID, ...

  8. Linux学习笔记——管道PIPE

    管道:当从一个进程连接数据流到另一个进程时,使用术语管道(pipe).# include <unistd.h> int pipe(int filedes[2]); //创建管道 pipe( ...

  9. [转帖]linux学习问题总结

    linux学习问题总结 https://www.cnblogs.com/chenfangzhi/p/10661946.html 学习作者的思路 目录 一.环境变量和普通变量的区别 二.rsyslog和 ...

  10. Linux系统编程—信号捕捉

    前面我们学习了信号产生的几种方式,而对于信号的处理有如下几种方式: 默认处理方式: 忽略: 捕捉. 信号的捕捉,说白了就是抓到一个信号后,执行我们指定的函数,或者执行我们指定的动作.下面详细介绍两个信 ...

随机推荐

  1. java中为什么要进行对象序列化?

    序列化其实很好理解,假如你现在做一个项目,项目是分工合作的,并且你喝其他小组成员不在同一个城市,那么你要如何把你写的那些类给其他小组成员呢?这个时候就要用到序列化了,简单的说:序列化就是将内存中的类或 ...

  2. HDU4436_str2int

    很好的一个题目.对于理解后缀自动机很有用. 题目给你若干数字串,总长度不超过100000,任意一个串的任意一个子串都可以拿出来单独的作为一个数字.同一个数字只算一次. 问所有不同数字的和为多少? 嗯嗯 ...

  3. winform 利用委托实现窗体传值

    父窗体:Form1    ,有个 textbox1.text ,有个button1 子窗体:Form2  ,有个 textbox1.text ,有个button1 修改Form1 的textbox1. ...

  4. .NET 复制对象会影响到复制源对象

    IList<string> list=new List<string>(); list.add("a"); list.add("b"); ...

  5. Raven: 2靶机入侵

    0x00 前言 Raven 2是一个中等难度的boot2root 虚拟靶机.有四个flag需要找出.在多次被攻破后,Raven Security采取了额外措施来增强他们的网络服务器安全以防止黑客入侵. ...

  6. Unhandled rejection RangeError: Maximum call stack size exceededill install loadIdealTree

    npm安装时候报这个错误,解决方法如下: 删除项目中的 package-lock.json 文件 和 node_modules 文件夹,然后再尝试 npm install 详细参考

  7. laravel Collection mapToDictionary 例子

    源码 示例 <?php require __DIR__ . '/bootstrap/app.php'; $arr = [ [ 'name' => 'John', 'age' => 2 ...

  8. windows10下R配置Rstdio,怎么处理

    首先要确保电脑上只有一个R程序,然后官网下载Rstdio安装包. 配置:选择Rstdio配置界面的第三项,然后关联到R的安装文件夹下的BIN文件夹即可. 但是,直接打开Rstdio的话,界面会一片空白 ...

  9. IAR ------- 在线调试技巧

    调试模式下,右击某一行选“Set Next Statement”,可以不执行中间程序,执行点直接到此行,用于不执行某些代码.

  10. Java入门:char与byte的区别

    byte 是字节数据类型 ,是有符号型的,占1 个字节:大小范围为-128—127 .char 是字符数据类型 ,是无符号型的,占2字节(Unicode码 ):大小范围 是0—65535 :char是 ...