Linux系统编程之信号处理函数signal与sigaction学习

信号(signal)是一种软件中断,它提供了一种处理异步事件的方法,也是进程间惟一的异步通信方式。那么我们很多场景下,需要对不同的信号进行捕获并做出响应操作。 系统提供了两种方式来处理信号:signal()和sigaction()。下面以定时器为例,说明这两个函数的用法。

一、 signal()函数
signal()函数说明

#include <signal.h>

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

定时器实例,singnal()函数实现。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>

void handler(int signo)
{
	time_t t = time(NULL);
	printf("%d\t%s", signo, ctime(&t));
	alarm(5);
}

int main(void)
{
	signal(SIGALRM, handler);
	alarm(5);
	while(1) pause();
	return 0;
}

运行结果

[ycxie@fedora Workspace]$ gcc signaldemo.c -o signaldemo -Wall
[ycxie@fedora Workspace]$ ./signaldemo
14	Mon Sep 24 14:00:00 2018
14	Mon Sep 24 14:00:05 2018
14	Mon Sep 24 14:00:10 2018
14	Mon Sep 24 14:00:15 2018
14	Mon Sep 24 14:00:20 2018
14	Mon Sep 24 14:00:25 2018

二、 sigaction()函数
sigaction()函数说明

#include <signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
struct sigaction {
    void     (*sa_handler)(int);
    void     (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t   sa_mask;
    int        sa_flags;
    void     (*sa_restorer)(void);
};
// The siginfo_t data type is a structure with the following fields:
siginfo_t {
    int      si_signo;     /* Signal number */
    int      si_errno;     /* An errno value */
    int      si_code;      /* Signal code */
    int      si_trapno;    /* Trap number that caused
                              hardware-generated signal
                              (unused on most architectures) */
    pid_t    si_pid;       /* Sending process ID */
    uid_t    si_uid;       /* Real user ID of sending process */
    int      si_status;    /* Exit value or signal */
    clock_t  si_utime;     /* User time consumed */
    clock_t  si_stime;     /* System time consumed */
    sigval_t si_value;     /* Signal value */
    int      si_int;       /* POSIX.1b signal */
    void    *si_ptr;       /* POSIX.1b signal */
    int      si_overrun;   /* Timer overrun count;
                              POSIX.1b timers */
    int      si_timerid;   /* Timer ID; POSIX.1b timers */
    void    *si_addr;      /* Memory location which caused fault */
    long     si_band;      /* Band event (was int in
                              glibc 2.3.2 and earlier) */
    int      si_fd;        /* File descriptor */
    short    si_addr_lsb;  /* Least significant bit of address
                              (since Linux 2.6.32) */
    void    *si_lower;     /* Lower bound when address violation
                              occurred (since Linux 3.19) */
    void    *si_upper;     /* Upper bound when address violation
                              occurred (since Linux 3.19) */
    int      si_pkey;      /* Protection key on PTE that caused
                              fault (since Linux 4.6) */
    void    *si_call_addr; /* Address of system call instruction
                              (since Linux 3.5) */
    int      si_syscall;   /* Number of attempted system call
                              (since Linux 3.5) */
    unsigned int si_arch;  /* Architecture of attempted system call
                              (since Linux 3.5) */
}

定时器实例,singnal()函数实现。

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>

void handler(int signo)
{
	time_t t = time(NULL);
	printf("%d\t%s", signo, ctime(&t));
	alarm(5);
}

int main(void)
{
	struct sigaction act;

	act.sa_handler = handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;

	sigaction(SIGALRM, &act, NULL);
	alarm(5);
	while(1) pause();
	return 0;
}

运行结果

[ycxie@fedora Workspace]$ gcc sigactiondemo.c -o sigactiondemo -Wall
[ycxie@fedora Workspace]$ ./sigactiondemo
14	Mon Sep 24 14:06:47 2018
14	Mon Sep 24 14:06:52 2018
14	Mon Sep 24 14:06:57 2018
14	Mon Sep 24 14:07:02 2018
14	Mon Sep 24 14:07:07 2018
14	Mon Sep 24 14:07:12 2018

Leave a Reply

Your email address will not be published. Required fields are marked *