4212|1

241

帖子

4

TA的资源

纯净的硅(初级)

楼主
 

Helper2416-34——Linux_Programing——信号 [复制链接]

本帖最后由 yuanlai2010 于 2014-8-23 20:13 编辑

信号
参与Helper2416开发板助学计划心得

什么是信号
信号是UNIX和Linux系统相应某些条件而生成的一个事件.接收到该信号的进程会相应地采取一些行动。

信号生成
信号是由于某些错误条件产生的:也可以作为在进程间传递消息或修改行为的一种方式,明确的由一个进程发送给另一个进程。

信号处理
当某信号出现时,将按照以下三种方式中的一种进行处理:

1、忽略此信号
大多数信号都是按照这种方式处理,但是有两种信号却不能被忽略(SIGKILL 和 SIGSTOP)。这两种信号不能被忽略的原因是:他们向超级用户提供了一种终止或停止进程的方法。

2、执行用户希望的动作
通知内核在某种信号发生时,调用一个用户函数。在用户函数中,执行用户希望的处理
信号处理的主要方法主要有两种:一种是用简单的signal函数吗,另一种是使用信号集函数组。

3、执行系统默认动作
对大多数信号的系统默认动作是终止该进程

信号发送
发送信号的主要函数有kill和raise
区别
Kill既可以向自身发送信号,也可以向其他进程发送信号。与kill函数不同的是,raise函数是向进程自身发送信号

Raise
函数原形:int raise(int sig);
函数功能:将参数sig指定的信号发送给自身进程,使用 kill -l 命令可查看linux系统中信号。
函数返回:执行成功则返回0,如果有错误则返回-1。
参数说明:sig指定信号。
头表文件:#include
                #include

Kill
函数原形:int kill(pid_t pid,int sig);
函数功能:传送信号给指定的进程,使用 kill -l 命令可查看linux系统中信号。
函数返回:执行成功则返回0,如果有错误则返回-1。
          错误代码
            EINVAL 参数sig 不合法
            ESRCH 参数pid 所指定的进程或进程组不存在
            EPERM 权限不够无法传送信号给指定进程
参数说明:sig指定的信号;pid指定的进程。
头表文件:#include
          #include

函数说明:
          kill()可以用来送参数sig指定的信号给参数pid指定的进程。参数pid有几种情况:
          pid>0 将信号传给进程识别码为pid 的进程。
          pid=0 将信号传给和当前进程相同进程组的所有进程
          pid=-1 将信号广播传送给系统内所有的进程
          pid<0 将信号传给进程组识别码为pid绝对值的所有进程

参数sig代表的信号:
  
Signal
  
Description
SIGABRT
由调用abort函数产生,进程非正常退出
SIGALRM
用alarm函数设置的timer超时或setitimer函数设置的interval timer超时
SIGBUS
某种特定的硬件异常,通常由内存访问引起
SIGCANCEL
由Solaris Thread Library内部使用,通常不会使用
SIGCHLD
进程Terminate或Stop的时候,SIGCHLD会发送给它的父进程。缺省情况下该Signal会被忽略
SIGCONT
当被stop的进程恢复运行的时候,自动发送
SIGEMT
和实现相关的硬件异常
SIGFPE
数学相关的异常,如被0除,浮点溢出,等等
SIGFREEZE
Solaris专用,Hiberate或者Suspended时候发送
SIGHUP
发送给具有Terminal的Controlling  Process,当terminal被disconnect时候发送
SIGILL
非法指令异常
SIGINFO
BSD signal。由Status Key产生,通常是CTRL+T。发送给所有Foreground Group的进程
SIGINT
由Interrupt Key产生,通常是CTRL+C或者DELETE。发送给所有ForeGround Group的进程
SIGIO
异步IO事件
SIGIOT
实现相关的硬件异常,一般对应SIGABRT
SIGKILL
无法处理和忽略。中止某个进程
SIGLWP
由Solaris Thread Libray内部使用
SIGPIPE
在reader中止之后写Pipe的时候发送
SIGPOLL
当某个事件发送给Pollable Device的时候发送
SIGPROF
Setitimer指定的Profiling Interval Timer所产生
SIGPWR
和系统相关。和UPS相关。
SIGQUIT
输入Quit Key的时候(CTRL+\)发送给所有Foreground Group的进程
SIGSEGV
非法内存访问
SIGSTKFLT
Linux专用,数学协处理器的栈异常
SIGSTOP
中止进程。无法处理和忽略。
SIGSYS
非法系统调用
SIGTERM
请求中止进程,kill命令缺省发送
SIGTHAW
Solaris专用,从Suspend恢复时候发送
SIGTRAP
实现相关的硬件异常。一般是调试异常
SIGTSTP
Suspend Key,一般是Ctrl+Z。发送给所有Foreground  Group的进程
SIGTTIN
当Background Group的进程尝试读取Terminal的时候发送
SIGTTOU
当Background Group的进程尝试写Terminal的时候发送
SIGURG
当out-of-band data接收的时候可能发送
SIGUSR1
用户自定义signal 1
SIGUSR2
用户自定义signal 2
SIGVTALRM
setitimer函数设置的Virtual Interval Timer超时的时候
SIGWAITING
Solaris Thread Library内部实现专用
SIGWINCH
当Terminal的窗口大小改变的时候,发送给Foreground  Group的所有进程
SIGXCPU
当CPU时间限制超时的时候
SIGXFSZ
进程超过文件大小限制
SIGXRES
Solaris专用,进程超过资源限制的时候发送

Pause
函数原形:Int pause(void)
函数功能:Pause函数使用调用进程挂起直至捕捉到一个信号。
头表文件:#include
函数说明:只有执行了一个信号处理函数后,挂起才结束。

信号处理、执行用户希望动作的具体方法:

signal
函数原形:void (*signal(int sig, void (*fanc)(int))) (int);
                    或者:typedef void (*sig_t)( int );
                    sig_t signal(intsignum,sig_t handler);
函数功能:设置某一信号的对应动作。
函数返回:返回先前的信号处理函数指针,如果有错误则返回SIG_ERR(-1)。
参数说明:第一个参数signum指明了所要处理的信号类型,它可以取除了SIGKILL和SIGSTOP外的任何一种信号。
          第二个参数handler描述了与信号关联的动作,它可以取以下三种值:
         (1)一个无返回值的函数地址
          此函数必须在signal()被调用前申明,handler中为这个函数的名字。当接收到一个类型为sig的信号
          时,就执行handler 所指定的函数。这个函数应有如下形式的定义:
          void func(int sig);
         (2)SIG_IGN
          这个符号表示忽略该信号,执行了相应的signal()调用后,进程会忽略类型为sig的信号。
         (3)SIG_DFL
          这个符号表示恢复系统对信号的默认处理。
头表文件:#include

通过signal设置好信号对应的动作后,就可以来捕获对应的信号,然后响应相应的动作。
实践代码:
  1. #include <signal.h>
  2. #include <sys/types.h>
  3. #include <stdio.h>
  4. #include <unistd.h>
  5. #include <stdlib.h>

  6. void Signal_Handler(int sig)
  7. {
  8.         if(SIGINT == sig){
  9.                 printf("\nReceive signal SIGINT\n");
  10.                 signal(SIGINT, SIG_DFL);
  11.         }
  12.         if(SIGUSR1== sig){
  13.                 printf("Receive signal SIGUSR1\n");
  14.                 printf("This PID is %d",getpid());
  15.         }
  16. }

  17. int main()
  18. {
  19.         signal(SIGINT, Signal_Handler);
  20.         signal(SIGUSR1,Signal_Handler);
  21.         printf("%d Waiting for signal\n",getpid());
  22.         raise(SIGUSR1);
  23.         while(1){
  24.                 printf("hello world!\n");
  25.                 sleep(1);
  26.         }
  27. }
复制代码

运行结果:
  1. [jyxtec@localhost signal]$ ./signal0
  2. 3273 Waiting for signal
  3. Receive signal SIGUSR1
  4. This PID is 3273hello world!
  5. hello world!
  6. hello world!
  7. hello world!
  8. ^C
  9. Receive signal SIGINT
  10. hello world!
  11. hello world!
  12. ^C
  13. [jyxtec@localhost signal]$
复制代码

这个例子中通过设置信号SIGUSR1对应动作答应出当前进程的PID,并使用raise给自身发送此信号,同时设置信号SIGINT(按下Ctrl + C产生此信号 如果没有设置捕获此信号的话,默认情况下会终止当前前台正在运行的进程)的对应动作来打印一条消息,打印完后把此信号的处理方式修改为默认方式,最后用Ctrl + C来终止程序运行。

论坛ID:yuanlai2010
发表时间:2014-08-23

最新回复

不错,继续加油,也像洗澡哥那样,移植个游戏玩玩!呵呵  详情 回复 发表于 2014-8-23 20:48
点赞 关注

回复
举报

554

帖子

0

TA的资源

版主

沙发
 
不错,继续加油,也像洗澡哥那样,移植个游戏玩玩!呵呵
 
个人签名My dreams will go on...
http://www.jyxtec.com
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表