Linux——信号相关的概念和机制、Linux常见信号、kill函数、alarm函数、setitimer函数

终于信号了!!!冲啊 5月第一天,进度稍稍慢了,加油加油

一、信号的机制

A给B发送信号,B收到信号之前执行自己的代码,收到信号后不管执行程序到什么位置了,都要暂停运行,去处理信号,信号处理完毕再继续执行。

信号的特质:由于信号是通过软件方法实现的,其实现手段导致信号有很强的延时性,但对于用户来说,这个延迟不易察觉

每个进程收到的所有信号,都是由内核负责发送的,内核处理

1. 与信号相关的事件和状态

产生信号:

  1. 按键产生,如ctrl+c、ctrl+z、ctrl+\
  2. 系统调用产生,如kill、raise、abort
  3. 软件条件产生,如alarm
  4. 硬件异常产生,如非法访问内存(段错误)、除0(浮点数例外)、内存对齐出错(总线出错)
  5. 命令产生,如kill

状态:

  1. 递达:递送且到达进程
  2. 未决:产生和递达之间的状态,主要由于阻塞(屏蔽)导致该状态

信号处理的方式:
1,执行默认动作
2,忽略(丢弃)
3,捕捉(调用户处理函数)

Linux内核的进程控制块PCB是一个结构体,task_struct,除了包含进程id、状态、工作目录、用户id、组id、文件描述符,还包含了信号相关的信息,主要指阻塞信号集和未决信号集。

阻塞信号集(信号屏蔽字): 将某些信号加入集合,对它们设置屏蔽,当屏蔽信号x后,再收到该信号对该信号的处理将退后(解除屏蔽后)
未决信号集:

  1. 信号产生,未决信号集中描述该信号的位立即翻转为1,表信号处于未决状态。当信号被处理对应位翻转回0
  2. 信号产生后由于某些原因(主要是阻塞)不能抵达,这类信号的集合称为未决信号集。在接触屏蔽钱,信号一直处于未决状态

二、Linux常见信号

可通过man 7 signal帮助文档查看,<font #color = cc0033>注意9)SIGKILL和19)SIGSTOP信号,不允许忽略和捕捉,只能执行默认动作,甚至不能将其设置为阻塞
另外需注意,只有每个信号所对应的事件发生了,该信号才会被递送(但不一定递达),不能乱发信号

对每个信号要掌握其四要素:1编号; 2名称; 3事件; 4默认处理动作
默认动作有:
Term:终止进程
Ign:忽略信号(默认即时对该种信号忽略操作
Core:终止进程,生成Core文件(查验进程死亡原因,用于gdb调试
Stop:停止(暂停)进程
Cont:继续运行进程


1)SIGHUP:用户退出shell时,由该shell启动的所有进程将收到这个信号,默认动作为终止进程
2)SIGINT:当用户按下<ctrl+C>,用户终端向正在运行中的由该终端启动的程序发出信号,默认动作为终止进程
3)SIGQUIT:当用户按下<ctrl+>,用户终端向正在运行中的由该终端启动的程序发出信号,默认动作为终止进程(跟2)一样?
7)SIGBUS:非法访问内存地址,包括内存对齐出错,默认动作为终止进程并产生core文件
8)SIGFPE:在发生致命的运算错误时发出,不仅包括浮点运算错误,还包括溢出及除数为0等所有的算法错误。默认动作为终止进程并产生core文件
9)SIGKILL:无条件终止进程。本信号不能被忽略,处理和阻塞。默认动作为终止进程。它向系统管理员提供了可以杀死任何进程的方法
10)SIGUSR1:用户定义的信号,即程序员可以在程序中定义并使用该信号。默认动作为终止进程
11)SIGSEGV:指示进程进行了无效内存访问。默认动作为终止进程并产生core文件
12)SIGUSR2:另外一个用户自定义信号,程序员可以在程序中定义并使用该信号,默认动作为终止进程
13)SIGPIPE:Broken pipe向一个没有读端的管道写数据,默认动作为终止进程
14)SIGALRM:定时器超时。超时的时间由系统调用alarm设置。默认动作为终止进程
15)SIGTERM:程序结束信号,与SIGKILL不同的是,该信号可以被阻塞和终止,通常用来表示程序正常退出。执行shell命令kill时,缺省产生这个信号,默认动作为终止进程
17)SIGCHLD:子进程状态发生变化,父进程会收到这个信号。默认动作为忽略这个信号
19)SIGSTOP:停止进程的执行。信号不能被忽略,处理和阻塞。默认动作为暂停进程

中断按键产生的信号
Ctrl+c ——>2)SIGINT(终止/中断) “INT”----Interrupt
Ctrl+z ——>20)SIGSTOP(暂停/停止) “T”----Terminal
Ctrl+\ ——>3)SIGQUIT(退出)

硬件产生的信号:
除0操作——>8)SIGFPE(浮点数例外) “F”—float
非法访问内存——>11)SIGSEGV(段错误)
总线错误——>7)SIGBUS

三、Kill函数和kill命令

int kill(pit_t pid, int sig):成功返回0,失败返回-1;
pid>0:发送信号给指定进程
pid=0:发送信号给 与调用kill函数进程pid>0
pid<-1:取pid绝对值发给对应进程组
pid=-1:发送给进程有权限发送的系统中的所有进程(杀伤力极大,就不要尝试了

kill函数有权限保护,super用户可以发送信号给任意用户,普通用户时不能像系统用户发送信号的。普通用户的基本规则是:发送者实际或有效用户ID == 接收者实际或有效用户ID

四、alarm函数

设置定时器(闹钟)。在指定seconds后,内核会给当前进程发送14SIGALRM信号。进程收到该信号,默认动作终止
每个进程都有且只有唯一一个定时器
unsigned int alarm(unsigned int seconds):返回0或剩余的描述,无失败
常用情况:alarm(0),气胸定时器,返回旧闹钟剩余的秒数
alarm的定时与进程状态无关,不管是就绪状态,运行状态还是挂起,终止,僵尸……alarm都计时
另外,可以用time命令查看程序执行时间
实际执行时间 = 系统时间+用户时间+等待时间

其他几个发信号函数:
int raise(int sig);
void abort(void);

五、setitimer函数

设置定时器(闹钟),可代替alarm函数,精度到微秒,可以实现周期定时

int setitimer(int which, const struct itimerval *new_value, sturct itimerval *old_value);
成功返回0,失败返回-1,设置errno
参数:which,指定定时方式
①自然定时:ITIMER_REAL---->14)SIGALRM 、计算自然时间
②虚拟空间定时(用户空间):ITIMER_VIRTUAL---->26)SIGTALRM 、只计算cpu及执行系统调用的时间
③运行时及时(用户+内核):ITIMER_PROF---->27)SIGPROF 、计算cpu及执行系统调用的时间

其中第二个new_value是定时秒数,第三个参数是各传出参数,显示上次定时剩余时间,它们的参数类型itimerval 是一个结构体,一个结构体内嵌套着结构体的类型

struct itimerval
{
	struct timeval it_interval;//下一个时间值
	struct timeval it_value;//当前的时间
}

//每个时间又是由秒+微秒组成的

struct itimerval
{
	struct timerval
	{
		time_t tv_sec;//秒
		suseconde_t tv_usec;//微秒
	}it_interval;
	struct timeval
	{
		time_t tv_sec;//秒
		suseconds tv_usec;//微秒
	}it_value;
}
原创文章 119 获赞 27 访问量 5991

猜你喜欢

转载自blog.csdn.net/qq_37299596/article/details/105865696
今日推荐