22、linux信号学习(1)

 1、最简单的安装信号

示例1

View Code
#include <iostream>
using namespace std;
#include <signal.h>

void func(int sig)
{
cout<<"用户自定义"<<endl;
}
int main()
{
signal(SIGUSR1,func);
pid_t pid = getpid();
kill(pid, SIGUSR1);/*用户自定义信号,kill具有发信号的功能,这行代码向“自身进程pid发信号SIGUSR1,执行的最终结果是触发SIGUSR1信号*/
}

2、更高层软件形式的异常,称为unix信号,它允许进程中断其他进程。一个信号(signal)就是一条消息,它通知进程一个某种类型的事件已经在系统中发生了。Linux支持30种不同类型的信号。

调用kill函数可以向指定进程发出指定的信号,调用raise函数,可以使进程向自己发送指定的信号,alarm可以使进程向自己经过指定的秒数后发送SIGALRM信号。

wps_clip_image-9923

SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。

SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。

SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler

    sigset_t类型对于每种信号用一个bit表示“有效”或“无效”状态,至于这个类型内部如何存储这些bit则依赖于系统实现。

3、unix shell 使用作业(job)的抽象概念来表示求值一条命令行而产生的进程。在任何时刻,到多只有一个前台作业和0个或式个后台作业。shell为每个作业创建一个独立的进程组。

4、函数

1)alarm

#include<unistd.h>

unsigned int alarm(unsigned int seconds);

    alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程。如果参数seconds 0,则之前设置的闹钟会被取消,并将剩下的时间返回。

alarm示例

View Code
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

void handler(int sig)
{
printf("hello\n");
}

int main()
{
int i;
signal(SIGALRM, handler);
alarm(5);
for (i = 0; i < 7; i++)
{
printf("sleep %d ...\n", i);
sleep(1);

}
return 0;
}

2)kill

#include <sys/types.h>

#include <signal.h>

int kill(pid_t pid, int sig);

The kill() system call can be used to send any signal to any process group or process.

    kill()用来送指定的信号sig给参数pid指定的进程。参数pid有几种情况:

pid>0 将信号传给进程识别码为pid 的进程。

pid=0 将信号传给和目前进程相同进程组的所有进程

pid=-1 将信号广播传送给系统内所有的进程

pid<0 将信号传给进程组识别码为pid绝对值的所有进程

3)int pause(void);

    pause()会令目前的进程暂停(进入睡眠状态),直到被信号(signal)所中断。

int raise(int sig);

//The raise() function sends a signal to the current process. It is equivalent to kill(getpid(), sig);

4)#include<signal.h>

int sigaction(int signum,const struct sigaction *act ,struct sigaction *oldact);

    sigaction()会依参数signum指定的信号编号来设置该信号的处理函数。参数signum可以指定SIGKILLSIGSTOP以外的所有信号。

struct sigaction

{

void (*sa_handler) (int);

sigset_t sa_mask;

int sa_flags;

void (*sa_restorer) (void);

}

sa_handler参数和signal()的参数handler相同,代表新的信号处理函数;

sa_mask 用来设置在处理该信号时暂时将sa_mask指定的信号搁置。sa_mask gives a mask of signals which should be blocked during execution of the signal handler. In addition, the signal which triggered the handler will be blocked, unless the SA_NODEFER flag is used.

sa_restorer 此参数没有使用。

sa_flags 用来设置信号处理的其他相关操作。OR运算(|)组合:

a. A_NOCLDSTOP : 如果参数signumSIGCHLD,则当子进程暂停时并不会通知父进程

b. SA_ONESHOT/SA_RESETHAND:当调用信号处理函数前,将此信号处理方式改为缺省值;SA_RESETHAND是这个标记的正式的POSIX名字,为了软件的可移植性,一般不用SA_ONESHOT

c. SA_RESTART:被信号中断的系统调用会自行重启

d. SA_NOMASK/SA_NODEFER:在处理此信号未结束前不理会此信号的再次到来。SA_NODEFER是这个标记的正式的POSIX名字,为了软件的可移植性,一般不用SA_NOMASK)

    如果参数oldact不是NULL指针,则原来的信号处理方式会由此结构sigaction 返回。

示例代码

View Code
#include <unistd.h>
#include <signal.h>
#include <iostream>
#include <cstdio>

using namespace std;

void show_handler(int sig)
{
cout << "I got signal " << sig << endl;
for (int i = 0; i < 5; i++)
{
cout << "i = " << i << endl;
sleep(1);
}
}

int main()
{
int i;
struct sigaction act, oldact;
act.sa_handler = show_handler;
act.sa_flags = SA_RESETHAND | SA_NODEFER;
sigaddset(&act.sa_mask, SIGQUIT); //屏蔽ctrl+\信号
//sigaction(SIGUSR1, &act, &oldact);
sigaction(SIGINT, &act, &oldact);
while(1)
{
sleep(1);
cout << "sleeping " << i << endl;
i++;
//kill(getpid(), SIGUSR1); //通过kill,向当前进程进行发送信号SIGUSR1
}
}


原文地址:https://www.cnblogs.com/mydomain/p/2184355.html