关于信号

一、基本概念
1、中断
停止当前正在执行的任务,转而执行其它任务,这中行为叫中断。
硬件中断:来自硬件的中断。
软件中断:来自软件的中断。

2、信号是一种软件中断
它为进程异步执行任务提供了一种机制。

3、常见的信号
SIGINT 终端中断符信号 Ctrl+c 发出
SIGQUIT 终端退出符信号 Ctrl + \ 发出
SIGFPE 算术异常信号 程序执行的除0操作
SIGSEGV 段错误停下 非法使用了内存
SIGSTOP 暂停信号 不能被捕获、忽略,收到SIGCONT信号才能继续
SIGCONT 继续停下 可以让停止的进程继续执行

4、不可靠信号
kill -l可以显示出所有可用的信号。
1至31 是建立在早期的机制上的,不支持排队,同一个信号多次产生时只处理一次,但这种机制可能会导致信号丢失。

5、可靠信号
34至64,是一种新机制的信号,支持排队,不会丢失。

6、信号的处理
1、忽略
2、终止
3、终止+core(记录内存的使用情况)
1、执行:ulimit -c unlimited,使用系统能够生成core文件。
2、重新编译:gcc -g code.c 加入调试信息。
3、重新执行程序,生成带调试信息的core文件。
4、使用gdb a.out core 进入调试。
5、where显示在什么位置什么原因产生的错误。
4、捕获并处理,当信号发生时操作会调用一个预先注册好的一个处理函数。

二、信号的捕获

typedef void (*sighandler_t)(int); //信号处理函数的格式
sighandler_t  signal(int signum, sighandler_t han‐dler);
功能:向内核注册一个信号处理函数
signum:要捕获并处理的信号
han‐dler:当信号发生时要执行的函数
注意:这个步骤一般写在程序开始部分(项目初始化阶段)

代码产生(除0、非法使用内存)的信号,这种通信能被捕获,但是当信号处理完后又会回到产生错误的位置,如果这个错误没有消除又会继续产生信号,会形成死循环,解决方法就是把数据保存,然后安全结束。

三、发送信号
1、键盘发送信号
Ctrl+c SIGINT
Ctrl+\ SIGQUIT
Ctrl+z SIGSTOP
2、错误产生信号
除0操作 SIGFPE
非法访问内存 SIGSEGV
硬件故障 SIGBUS
3、命令发送信号
kill -sig 进程号
killall -sig 程序名 向所以叫这个名字的进程发送信号
4、函数发送信号
int kill(pid_t pid, int sig);
功能:向指定的进程发送信号
pid:
pid > 0 向指定的进程发送信号
pid = 0 向同组的进程发送信号
pid = -1 向所以有权限发送信号的进程发送信号
普通用户只能对自己的进程发送信号,而root可以向所有的进程发送信号。
pid < -1 向进程号等于pid绝对值的进程发送信号。

	sig:信号的编号
		如果sig的值不存在,不会发送,但也不会返回错误。
		当发送的进程不存在时,才会返回错误,这个功能可以用来检查一个进程是否存在。
		
	int raise(int sig);
	功能:向当前进程发送信号

四、pause、sleep

int pause(void);
功能:使用进程进入休眠状态,直到有信号来临(信号处理函数执行完毕)才醒来。
返回值:函数结束返回-1,否则进程一直休眠。

unsigned int sleep(unsigned int seconds);
功能:让调用都进入休眠,当信号来临时休眠会被中止提前返回(信号处理函数执行完毕后)。
seconds:要休眠的秒数
返回值:当睡够足够的秒数返回零,如果提前结束休眠则返回剩余的秒数。

int usleep(useconds_t usec);
功能:以微秒为单位进行休眠,1000000微秒 = 1秒
返回值:提前结束返回-1,正常结束返回0

五、闹钟信号

unsigned int alarm(unsigned int seconds);
功能:在seconds秒后产生闹钟信号
返回值:返回0成功设置,如果之前已经有设置过还没有到时间,则返回剩余时间。

六、信号集与信号屏蔽
1、信号集:多个信号的集合,sigset_t 是一个128位的二进制整数,每一位代表一个信号。
2、信号集相关函数:

	int sigemptyset(sigset_t *set);
	功能:将信号集设置为空,所有二进制位设置为0。
	
    int sigfillset(sigset_t *set);
	功能:将信号集设置为满,所有二进制位设置为1。
	
    int sigaddset(sigset_t *set, int signum);
    功能:向信号集中添加一个信号。

    int sigdelset(sigset_t *set, int signum);
    功能:从信号集中删除一个信号。

    int sigismember(const sigset_t *set, int signum);
    功能:查询信号集中是否有某个信号存在
    返回值:存在返回1,不存在返回0,错误信号返回-1。
    
3、信号屏蔽
	当信号产生时,系统内核在会其维护的进程表中,为特定的进程设置一个与该信号相对应的标志位,这个过程叫递送。
	信号从产生到完成递关之间存在一段时间的间隔,这段时间的信号状态叫末决。
	每个进程都有一个信号掩码,它实际上是一个信号集,其中包含了所要屏蔽的信号。
	当处理一些敏感操作时不希望被中断(更新数据库、加载文件、保存文件),可以使用sigprocmask暂屏蔽一些信号,让这些信号处于未决状态。
	当这此敏感操作处理完成后,再使用sigpending获取这段时间发生的信号。
	int  sigprocmask(int  how,  const  sigset_t  *set,sigset_t *oldset);
	功能:设置信号屏蔽掩码
	how:
   		SIG_BLOCK:屏蔽掩码=旧 并 新
   		SIG_UNBLOCK:屏蔽掩码=旧 交 新
   		SIG_SETMASK:屏蔽掩码=新
   	oldset:
   		返回旧的屏蔽掩码

	int sigpending(sigset_t *set);
	功能:获取未决状态的信号集

七、带附加信息的信号捕获和发送

int sigaction(int signum, const struct sigaction *act,
                 struct sigaction *oldact);
功能:设置信号处理方式
act:新设置信号处理方式
oldact:获取旧的信号处理方式,为NULL则不获取

sigaction结构体的成员:
	void (*sa_handler)(int); 信号处理函数1
    void (*sa_sigaction)(int,siginfo_t *,void *);信号处理函数2
    sigset_t   sa_mask; 信号处理过程中屏蔽掩码
    int  sa_flags;
    	 SA_NOCLDSTOP:如果signum的值是SIGCHLD,当子进程结束时不通知父进程。
    	 SA_NODEFER/SA_NODEFER:不屏蔽正在处理的信号
    	 SA_RESETHAND/SA_ONESHOT:当信号处理一次后,恢复默认处理方式。
    	 SA_RESTART:如果信号中断了系统调用,当信号处理完成后,重启系统调用。
    	 SA_SIGINFO:使用信号处理函数2
    void (*sa_restorer)(void); 保留,暂时没有使用

int sigqueue(pid_t pid, int sig, const union sig-val value);
功能:发送带参的信号
pid:要发的进程
sig:要发的信号
value:附加的的数据,指针可整数。

八、计时器
计时器是用来记录进程的运行时间的,系统会为每个进程记录三个计时器:
真实计时器:程序实际运行的时间
虚拟计时器:程序在用户态所消耗的时间
实用计时器:程序在内核态加用户态所消耗的时间之和
程序的实际运行时间=用户时间+内核时间+睡眠时间

使用计时器设置定时操作:
	先设置一个时间a,表示时钟信号在a时间后发生,再设置一个时间b,表示以后每隔b时间来一次。
	int getitimer(int which, struct itimerval *curr_value);
	功能:设置当前的时钟设置
	which:计时器的类别
		ITIMER_REAL/SIGALRM 真实计时器
		ITIMER_VIRTUAL/SIGVTALRM 虚拟计时器
		ITIMER_PROF/SIGPROF 实用计算器
		
	struct itimerval 结构体
           struct timeval it_interval;  间隔时间
           struct timeval it_value;  首次产生的时间

    struct timeval 结构体
           long tv_sec; 	秒数
           long tv_usec;    微秒

	int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);
	功能:设置新的时钟
	which:选择计时器和信号类型
	new_value:新设置的计时器
	old_value:获取旧的计时器
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值