栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

信号基础和信号函数大概介绍

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

信号基础和信号函数大概介绍

信号概念
  • 信号是软件中断。信号提供了一种处理异步事件的方法。
  • 不存在编号为0的信号(因为有特殊作用)
    -产生信号的方式有很多:终端键、硬件异常(除数为0、无效的内存引用等)、 kill函数、软件条件发生、关某种进程等
  • 信号处理:
    1. 忽略此信号(SIGKILL和SIGSTOP不可忽略)、捕捉信号、执行系统默 认动作(大多数是终止进程)
    2. 在系统默认动作列,”终止+core”表示在进程当前工作目录的core文件中复制了该进程的内存映像。大多数UNIX系统使用core文件来检查进程终止时的状态。
    3. 不产生core文件的条件:
      a.进程是设置用户ID的,而且当前用户非程序文件的所有者
      b.进程是设置组ID的,而且当前用户并非该程序文件的组所有者
      c.用户没有写当前工作目录的权限
      d.文件已存在,而且用户对该文件设有写权限
      e.文件太大
  • kill -l(linux指令,则可获取全部命令)
  • 不可靠信号
  1. 信号处理函数执行完毕,信号恢复成默认处理方式(Linux已经改进)
  2. 会出现信号丢失,信号不排队
  3. 1-31 都是不可靠的,会出现信号丢失现象
  4. 会出现同一信号多次发生只接收到一次的情况
  • 可靠信号
  1. 34-64不可靠信号
  2. 不会出现信号丢失,支持排队,信号处理函数执行完毕,不会恢复成缺省处理方式
  • 实时信号 : 就是可靠信号
  • 非实时信号:不可靠信号
  • SIGINT(Ctrl+C)
  • 注:每个信号的解析(请看其它文档)
信号捕捉函数
  • void (*signal(int sig,void(*func)(int)))(int)
  • 参数:
sig:要捕捉的信号
func: SIG_IGN   捕捉动作为:内核表示忽略此信号(预定义宏)
      SIG_DFL   捕捉动作为:执行该信号的系统默认动作
	  捕捉函数:执行由func指向的信号响应函数
      返回值:	成功:最近一次调用该函数时第二个参数的值
            	失败:SIG_ERR
  • 当执行一个程序时,接收信号的状态都是系统默认或忽略(根据信号来决定)
  • 注意:
    1. execl执行的进程,信号不会再捕捉了(具体看execl函数)
    2. fork后的子进程会继承父进程的信号处理方式
  • int sigaction(int signo,const struct sigaction* restrict act,
    struct sigaction* restrict oact)
参数:
 signo:信号值
 act: 非空 修改其动作
 oact:非空 返回该信号的上一个动作
 struct sigaction {
               void     (*sa_handler)(int);  //标准响应函数(不是常量SIG_IGN(信号忽略)和SIG_DFL(默认信号处理))
               void     (*sa_sigaction)(int, siginfo_t *, void 								*);    //备用响应函数,这两个函数一般										  只会响应一个               
			   sigset_t   sa_mask;//阻塞的信号集,信号捕捉成功恢复原先值
               int        sa_flags;//功能选择标记(见图10-16)
         	 };
         	 
void handler(int signo,siginfo_t* info,void* context);
		struct siginfo{
		int 	si_signo; //信号数字
		int 	si_errno; //错误编码
		int		si_code; //备注(取决于信号,见图10-17)
		pid_t		si_pid; //发送信号的进程的id
		uid_t		si_uid;//发送信号的用户id
		void		*si_addr;//造成故障的地址
		int			si_status;//信号退出值
		union sigval si_value;//信号传递的值
		}
			union sigval {
			int sival_int;//整数值
			void* sival_ptr;//指针值
			}
	返回值: 成功 0;出错 -1

-signal 例子:

#include 
#include 
#include 
#include 
#include 
#include 

void sig_int(int signo)
{
	printf("signal num = %dn",signo);
}

int main(int argc,char** argv)
{
	if(signal(SIGINT,sig_int) == SIG_ERR)
		perror("signal(SIGINT) errorn");
	
	raise(SIGINT);
	
	return 0;
}

可重入函数
  • 可重入函数是可以随时被中断,并不会影响程序运行的(异步信号安全的),信号处理操作期间,它会阻塞任何会引起不一致的信号发送
  • 大多数函数是不可重入的(信号处理中断函数会造成程序问题的):
    a. 已知它们使用静态数据结构
    b. 它们调用malloc或free
    c. 它们是标准I/O函数
  • 可重入函数(见百度)
发送信号函数
  • Int kill(pid_t pid,int sig) 给对应进程发送信号
  • 注意:要有权限才可以发送相对应的进程(一般同一个用户启动就可以)
pid: >0	发送给进程号为pid的进程
<-1	发送给组ID等于-pid的进程组里面的所有进程
0	信号发送给当前进程同一个进程组内的所有进程
-1		信号被发送给所有进程(如果当前进程对其有权限)
sig: 发送的信号值
返回值:   成功:0   失败:-1  
  • int raise(int signo) 给自身发送信号
  • unsigned int alarm(unsigned int seconds) 定时器信号啊函数
  • int sigqueue(pid_t pid,int signo,const union sigval value) 发送信号可附带数据(value共用体同sigaction参数中的共用体)
  • pause(void) 进程或线程休眠(遇到信号则退出休眠状态)
#include 
#include 
#include 
#include 
#include 

void sig_int(int signo,siginfo_t* info,void* context)
{
	printf("信号值:%d--->信号传递的值:%sn",signo,(char*)info->si_value.sival_ptr);
}

int main()
{
	struct sigaction act,oact;
	union sigval value;
	
	act.sa_handler = sig_int;
	act.sa_flags = SA_SIGINFO;//设置为传递信息
	if(sigaction(SIGUSR1,&act,&oact) == -1)//等待信号处理
		perror("sigaction(SIGINT)n");
	
	value.sival_ptr = "hello world";
	if(sigqueue(getpid(),SIGUSR1,value) == -1)
		perror("sigqueue errorn");
	
	return 0;
}

信号集
  • int sigemptyset(sigset_t* set);//清空信号集合
  • int sigfillset(sigset_t* set);//初始化信号集合,使其包括所有信号
  • int sigaddset(sigset_t* set,int signo);//增加信号到信号集
  • int sigdelset(sigset_t* set,int signo);//从信号集删除一个信号
  • int sigismember(const sigset_t* set,int signo); //测试一个指定的位是否被信号集包含(返回值: 1为真,0为假)
信号阻塞函数

可以检测或更改,或同时进行检测和更改进程的信号屏蔽字(屏蔽字:规定了当前阻塞而不能递送给该进程的信号集),SIGKILL和SIGTOP不能被阻塞

  • int sigprocmask(int how,const sigset_t* restrict set,sigset_t* restrict oset);
参数:      
			oset:		非空指针,		那么进程的当前信号屏蔽字通过oset返回(如果设置了屏蔽字,则在此时还是进程当前的屏蔽字)
						空指针,		不返回当前信号屏蔽字的内容
   			set:	 	非空指针,	则参数how指针如何修改当前信号屏蔽字
						空指针,		不改变该进程的信号屏蔽字,how的值也无意义
			how:  	SIG_BLOCK  	当前信号屏蔽字和set执行信号集的并集
					SIG_UNBLOCK	当前信号屏蔽字和set所指向信号集补集的交集(解除set信号集阻塞)
					SIG_SETMASK 	set所指向的值
sigprocmask函数调用后如果有任何未决的、不再阻塞的信号,则在sigprocmask返回前,至少将其中之一递送给该进程

例子:

#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
	sigset_t 	newmask,oldmask;
	
	sigemptyset(&newmask);
	sigfillset(&newmask);
	if(sigismember(&newmask,SIGINT))
		printf("SIGINT existn");
	
	if(sigismember(&newmask,SIGUSR1)) //因为sigfillset,所以有这个信号
		printf("SIGUSR1 existn");
	
	sigaddset(&newmask,SIGINT);//因为已经有了这个信号,所以无效
	sigdelset(&newmask,SIGINT);
	
	if(sigismember(&newmask,SIGINT) == 0)
		printf("not SIGINTn");
	
	if(sigprocmask(SIG_SETMASK,&newmask,&oldmask) < 0)
		perror("sigprocmask(SIG_BLOCK,NULL,&oldmask) errorn");
	
	if(sigismember(&oldmask,SIGUSR1) == 0) //因为是进程之前的信号集,所以没有这个信号
		printf("not SIGINTn");
	
	return 0;
}


#未完待续…

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/825555.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号