Linux中信号处理的两种方法

1、使用signal()函数和sigaction()

signal()函数原型

       #include <signal.h>
       typedef void (*sighandler_t)(int);
       sighandler_t signal(int signum, sighandler_t handler);

       signal() sets the disposition of the signal signum to handler, which is
       either SIG_IGN, SIG_DFL, or the address of a  programmer-defined  function (a "signal handler")
The signals SIGKILL and SIGSTOP cannot be caught or ignored. ——即信号SIGKILL和信号SIGSTOP不能被捕获或者忽略。
sigaction()函数原型
NAME
<pre>       sigaction - examine and change a signal action
SYNOPSIS
       #include <signal.h>
       int sigaction(int signum, const struct sigaction *act,
                     struct sigaction *oldact);
   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
       sigaction(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

If act is non-NULL, the new action for signal signum is installed  from
act.  If oldact is non-NULL, the previous action is saved in oldact.
The sigaction structure is defined as something like:
   struct sigaction {
       void     (*sa_handler)(int);
       void     (*sa_sigaction)(int, siginfo_t *, void *);
       sigset_t   sa_mask;
       int        sa_flags;
       void     (*sa_restorer)(void);
   };
On  some  architectures  a  union  is  involved:  do not assign to both
sa_handler and sa_sigaction.
The sa_restorer element is obsolete and should not be used.  POSIX does
not specify a sa_restorer element.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

/* Define the signal handle function */
void my_func(int sig_no)
{
	switch(sig_no)
	{
		case SIGINT:
			printf("I have get SIGINT\n");
			break;
		case SIGQUIT:
			printf("I have get SIGQUIT\n");
			break;
		default:
			break;
	}
}

int main()
{
	struct sigaction action;
	printf("Waiting for signal SIGINT or SIGQUIT...\n");

	/* Initialize the sigaction structure*/
	action.sa_handler = my_func;
	sigemptyset(&action.sa_mask);
	action.sa_flags = 0;

	/* Send certain signal and go to handle_fun */
	sigaction(SIGINT, &action, 0);
	sigaction(SIGQUIT, &action, 0);

	pause();
	alarm(3);

	printf("I'm over!\n");

	exit(0);
}

2、使用信号集函数组

调用的函数主要包括一下4个功能模块,创建信号集、注册信号处理函数及检测信号。
sigemptyset():将信号集初始化为空
sigfillset():  将信号集初始化为包含所有已定义的信号集。
sigaddset(): 将制定信号加入信号集中。
sigdelset():   将指定信号从信号集中删除。
sigismember():  查询指定信号是否在信号集中。
sigpending()函数允许进程检测“未处理“的信号,并进一步决定对它们做何处理。
说明:
注册信号处理函数主要用于决定进程如何处理信号,注意:信号集中的信号并不是真正可以处理的信号,只有当信号的状态处于非阻塞状态时才会真正起作用。所以一般使用sigprocmask()函数检测并更改信号屏蔽字(信号屏蔽字是指用来指定当前被阻塞的一组信号,它们不会被进程接收),然后使用sigaction()函数来定义进程接收到特定信号的行为。
信号处理的一般流程:

程序实例:
首先把SIGQUIT、SIGINT两个信号加入信号集,然后将该信号集设为阻塞状态,并进入用户输入状态。用户只需按任意键就可以立即将信号集设为非阻塞状态,再对这两个信号分别进行操作,其中SIGQUIT执行默认操作,而SIGINT执行用户自定义函数的操作。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>

/* Define the signal handle function */
void my_func(int sig_no)
{
	printf("If you want to quit, please try SIGQUIT\n");
}

int main()
{
	sigset_t set, pendset;
	struct sigaction action1, action2;

	/* step1: Initialize the sigset with Null. */
	if(sigemptyset(&set) < 0)
	{
		perror("sigemptyset");
		exit(1);
	}

	/* Add certain signal to sigset */
	if(sigaddset(&set, SIGQUIT) < 0)
	{
		perror("sigaddset");
		exit(1);
	}
	if(sigaddset(&set, SIGINT) < 0)
	{
		perror("sigaddset");
		exit(1);
	}

	if(sigismember(&set, SIGINT) < 0)
	{
		sigemptyset(&action1.sa_mask);
		action1.sa_handler = my_func;
		action1.sa_flags = 0;
		sigaction(SIGINT, &action1, NULL);
	}

	if(sigismember(&set, SIGQUIT) < 0)
	{
		sigemptyset(&action2.sa_mask);
		action2.sa_handler = my_func;
		action2.sa_flags = 0;
		sigaction(SIGQUIT, &action2, NULL);
	}

	/* step2: Set the value of mask word */
	if(sigprocmask(SIG_BLOCK, &set, NULL) < 0)
	{
		perror("sigprocmask");
		exit(1);
	}
	else
	{
		printf("Signal set was blocked, Press any key!\n");
		getchar();
	}

	/* Delete the signal of set */
	if(sigprocmask(SIG_UNBLOCK, &set, NULL) < 0)
	{
		perror("sigprocmask");
		exit(1);
	}
	else
	{
		printf("Signal set was unblocked, Press any key!\n");
	}

	while(1);
	exit(0);
}
时间: 2024-10-12 12:35:31

Linux中信号处理的两种方法的相关文章

Linux安装MySQL的两种方法

转载:http://blog.csdn.net/superchanon/article/details/8546254/ 1.       运行平台:CentOS 6.3 x86_64,基本等同于RHEL 6.3 2.       安装方法: 安装MySQL主要有两种方法:一种是通过源码自行编译安装,这种适合高级用户定制MySQL的特性,这里不做说明:另一种是通过编译过的二进制文件进行安装.二进制文件安装的方法又分为两种:一种是不针对特定平台的通用安装方法,使用的二进制文件是后缀为.tar.gz

RadioButon 获取单选按钮组选中值的两种方法!

在单选按钮中我们一般需要获得当前用户选择的按钮值是什么,想要得到用户的选择有两种方法. 第一种:在改变单选按钮组的值时获取.在改变单选按钮的值时获取选中项的值时,首先需要获取单选按钮组,然后为其添加OnCheckedChangeListener,并在onCheckedChanged()方法中根据参数checkedId获取被选中的单选按钮,并通过其getText()方法获取该单选按钮对应的值: 第二种:单击其他按钮时获取.首先需要在该按钮的单击事件的监听器的onClick()方法中,通过for循环

android 中传递对象两种方法探索(Serializable,Parcelable)

相信大家在android开发的过程中总会遇到要在Activity中间传递数据的情况,当然,遇到需要在Intent中传递对象的情况也不可避免,所以我就so了一下相关的知识,在这里总结消化一下.就目前来说,我了解到的只有两种方式: 1.利用Bundle.putSerializable(Key,Object): 2.利用Bundle.putParcelable(Key, Object): 下面详细介绍两种方法的使用和区别: 首先第一点,这两种方法实现的前提都需要将传递的对象Object序列化,那么,问

修改表中数据的两种方法(update改)

1.通过点击按钮来执行修改表中数据.(数据库和表的创建不在详细介绍,请自动阅读数据库和表的创建) 第一种方法:直接使用SQL来操作数据库,调用execSQL(sql)语句 public class MainActivity extends AppCompatActivity { private Button mPudateButton; private MySqliteHelper mMySqliteHelper; private SQLiteDatabase db; @Override pro

删除表中数据的两种方法(delete删)

1.通过点击按钮来执行删除表中数据.(数据库和表的创建不在详细介绍,请自动阅读数据库和表的创建) 第一种方法:直接使用SQL来操作数据库,调用execSQL(sql)语句 public class MainActivity extends AppCompatActivity { private Button mDeleteButton; private MySqliteHelper mMySqliteHelper; private SQLiteDatabase db; @Override pro

查询表中数据的两种方法(select查)

1.通过点击按钮来执行查询表中数据.(数据库和表的创建不在详细介绍,请自动阅读数据库和表的创建) 第一种方法:直接使用SQL来操作数据库,调用execSQL(sql)语句 public class MainActivity extends AppCompatActivity { private Button mSelectButton; private MySqliteHelper mMySqliteHelper; private SQLiteDatabase db; @Override pro

表中输入数据的两种方法(insert增)

1.通过点击按钮来执行往表中添加数据.(数据库和表的创建不在详细介绍,请自动阅读数据库和表的创建) 第一种方法:直接使用SQL来操作数据库,调用execSQL(sql)语句 public class MainActivity extends AppCompatActivity { private Button mInsertButton; private MySqliteHelper mMySqliteHelper; private SQLiteDatabase db; @Override pr

Delphi中创建对象的两种方法的比较(使用变量与直接创建)

比如创建一个线程有下面这样两种方式 begin TMyThread.Create; end; 和 var myTestThread: TMyThread; begin myTestThread:= MyThread.Create; end; 第一种方式就是创建了一个线程,这个线程去执行,但是你却没有这个线程对象的指针,所以你不能去控制它,只能任由它去执行,如果能自己结束还好,但是如果是一个循环执行的线程,那么就可能在那里永远执行下去,因为你在创建它的时候,没有记录这个线程对象的指针,所以你就没办

linux下时间同步的两种方法分享(转)

与一个已知的时间服务器同步 代码如下: ntpdate time.nist.gov 其中 time.nist.gov 是一个时间服务器. 删除本地时间并设置时区为上海 复制代码 代码如下: rm -rf /etc/localtimeln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 方法2:linux自动同步时间vi /etc/crontab加上一句: 复制代码 代码如下: 00 0 1 * * root rdate -s time.ni