linux C编程10-信号

目录

1、信号简介

2、信号掩码

3、等待信号集

4、信号产生

5、信号处理

6、信号查看

6.1、signum.h

6.2、kill -l

​ 7、信号分类 

8、实时信号的优势

9、常见信号

10、signal()函数

11、sigaction()函数

12、sigaction 结构体

13、siginfo_t 结构体

14、信号集

14.1、sigset_t结构体

14.2、sigemptyset()函数

14.3、sigfillset函数

14.4、sigaddset()函数

14.5、sigdelset()函数

14.6、sigismember()函数

15、获取信号的描述信息

15.1、sys_siglist 数组

15.2、strsignal()函数

15.3、psignal()函数

16、sigprocmask()函数

17、sigsuspend()函数

18、sigpending()函数

19、sigqueue()函数

20、kill()函数

21、raise()函数

22、alarm()函数

23、pause()函数

24、abort()函数


  

1、信号简介

信号是事件发生时对进程的通知机制,也可以把它称为软件中断。信号与硬件中断的相似之处在于能够打断程序当前执行的正常流程, 其实是在软件层次上对中断机制的一种模拟。 大多数情况下,是无法预测信号达到的准确时间,所以,信号提供了一种处理异步事件的方法。

2、信号掩码

内核为每一个进程维护了一个信号掩码。当进程接收到一个属于信号掩码中定义的信号时,该信号将会被内核阻塞、无法传递给进程进行处理,直到该信号从信号掩码中移除,内核才会把该信号传递给进程从而得到处理。

3、等待信号集

等待信号集只是一个掩码,仅表明一个信号是否发生,而不能表示其发生的次数。换言之,如果一个同一个信号在阻塞状态下产生了多次,那么会将该信号记录在等待信号集中,并在之后仅传递一次(仅当做发生了一次) ,这是标准信号的缺点之一。

4、信号产生

硬件发生异常即硬件检测到错误条件并通知内核,随即再由内核发送相应的信号给相关进程。硬件检测到异常的例子包括执行一条异常的机器语言指令,如,除数为 0、数组访问越界导致引用了无法访问的内存区域等,这些异常情况都会被硬件检测到,并通知内核、然后内核为该异常情况发生时正在运行的进程发送适当的信号以通知进程。
在终端下输入了能够产生信号的特殊字符譬如在终端上按下 CTRL + C 组合按键可以产生中断信(SIGINT),通过这个方法可以终止在前台运行的进程;按下 CTRL + Z 组合按键可以产生暂停信号(SIGCONT),通过这个方法可以暂停当前前台运行的进程。
进程调用 kill()系统调用接收信号的进程和发送信号的进程的所有者必须相同,亦或者发送信号的进程的所有者是 root 超级用户。
使用 kill 命令
 
kill命令其内部的实现原理便是通过 kill()系统调用来完成。普通用户只能杀死该用户自己的进程,无权限杀死其它用户的进程。
发生了软件事件
 
即当检测到某种软件条件已经发生。 这里指的不是硬件产生的条件(如除数为 0、引用无法访问的内存区域等),而是软件的触发条件、触发了某种软件条件(进程所设置的定时器已经超时、进程执行的 CPU 时间超限、进程的某个子进程退出等等况)。

5、信号处理

忽略信号当信号到达进程后,该进程并不会去理会它、直接忽略,信号对该进程不会产生任何影响(但有两种信号却决不能被忽略,它们是 SIGKILL 和 SIGSTOP,这两种信号不能被忽略的原因是:它们向内核和超级用户提供了使进程终止或停止的可靠方法。另外,如果忽略某些由硬件异常产生的信号,则进程的运行行为是未定义的)。
捕获信号当信号到达进程后,执行预先绑定好的信号处理函数。
执行系统默认操作每一种信号都会有其对应的系统默认的处理方式(对大多数信号来说,系统默认的处理方式就是终止该进程)。

6、信号查看

6.1、signum.h

/* Signals. */
#define SIGHUP 1 /* Hangup (POSIX). */
#define SIGINT 2 /* Interrupt (ANSI). */
#define SIGQUIT 3 /* Quit (POSIX). */
#define SIGILL 4 /* Illegal instruction (ANSI). */
#define SIGTRAP 5 /* Trace trap (POSIX). */
#define SIGABRT 6 /* Abort (ANSI). */
#define SIGIOT 6 /* IOT trap (4.2 BSD). */
#define SIGBUS 7 /* BUS error (4.2 BSD). */
#define SIGFPE 8 /* Floating-point exception (ANSI). */
#define SIGKILL 9 /* Kill, unblockable (POSIX). */
#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */
#define SIGSEGV 11 /* Segmentation violation (ANSI). */
#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */
#define SIGPIPE 13 /* Broken pipe (POSIX). */
#define SIGALRM 14 /* Alarm clock (POSIX). */
#define SIGTERM 15 /* Termination (ANSI). */
#define SIGSTKFLT 16 /* Stack fault. */
#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */
#define SIGCHLD 17 /* Child status has changed (POSIX). */
#define SIGCONT 18 /* Continue (POSIX). */
#define SIGSTOP 19 /* Stop, unblockable (POSIX). */
#define SIGTSTP 20 /* Keyboard stop (POSIX). */
#define SIGTTIN 21 /* Background read from tty (POSIX). */
#define SIGTTOU 22 /* Background write to tty (POSIX). */
#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */
#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */
#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */
#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */
#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */
#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */
#define SIGPOLL SIGIO /* Pollable event occurred (System V). */
#define SIGIO 29 /* I/O now possible (4.2 BSD). */
#define SIGPWR 30 /* Power failure restart (System V). */
#define SIGSYS 31 /* Bad system call. */
#define SIGUNUSED 31

6.2、kill -l

 7、信号分类 

Linux 系统下可对信号从两个不同的角度进行分类。从可靠性方面将信号分为可靠信号与不可靠信号;从实时性方面将信号分为实时信号与非实时信号。

注:Linux 下的不可靠信号问题主要指的是信号可能丢失。可靠信号支持排队,不会丢失。 

Linux 内核定义了 31 个不同的实时信号,信号编号范围为 34~64,使用 SIGRTMIN 表示编号最小的实时信号,使用 SIGRTMAX 表示编号最大的实时信号,其它信号编号可使用这两个宏加上一个整数或减去一个整数。

8、实时信号的优势

1、 实时信号的信号范围有所扩大,可应用于应用程序自定义的目的而标准信号仅提供了两个信号可用于应用程序自定义使用: SIGUSR1 和 SIGUSR2。
2、内核对于实时信号所采取的是队列化管理。如果将某一实时信号多次发送给另一个进程,那么将会多次传递此信号。相反,对于某一标准信号正在等待某一进程,而此时即使再次向该进程发送此信号,信号也只会传递一次。
3、当发送一个实时信号时,可为信号指定伴随数据(一整形数据或者指针值),供接收信号的进程在它的信号处理函数中获取。
4、不同实时信号的传递顺序得到保障。如果有多个不同的实时信号处于等待状态,那么将率先传递具有最小编号的信号换言之,信号的编号越小,其优先级越高,如果是同一类型的多个信号在排队,那么信号(以及伴随数据)的传递顺序与信号发送来时的顺序保持一致。

9、常见信号

SIGINT该信号的系统默认操作是终止进程的运行(当用户在终端按下CTRL + C))。
SIGQUIT当用户在终端按下退出字符(通常是 CTRL + \)时,内核将发送 SIGQUIT 信号给前台进程组中的每一个进程。该信号的系统默认操作是终止进程的运行、并生成可用于调试的核心转储文件。 进程如果陷入无限循环、或不再响应时,使用 SIGQUIT 信号就很合适。
SIGILL
 
如果进程试图执行非法(即格式不正确)的机器语言指令,系统将向进程发送该信号。该信号的系统默认操作是终止进程的运行。
SIGABRT
 
当进程调用 abort()系统调用时(进程异常终止) ,系统会向该进程发送 SIGABRT 信号。该信号的系统默认操作是终止进程、并生成核心转储文件。
 
SIGBUS
 
产生该信号(总线错误, bus error)表示发生了某种内存访问错误。该信号的系统默认操作是终止进程。
SIGFPE
 
该信号因特定类型的算术错误而产生,譬如除以 0。该信号的系统默认操作是终止进程。
SIGKILL
 
用于杀死进程的终极办法,此信号无法被进程阻塞、忽略或者捕获,故而“一击必杀”,总能终止进程。 
SIGUSR1
 
该信号和 SIGUSR2 信号供程序员自定义使用,内核绝不会为进程产生这些信号。 该信号的系统默认操作是终止进程。
SIGSEGV
 
这一信号非常常见,当应用程序对内存的引用无效时,操作系统就会向该应用程序发送该信号。该信号的系统默认操作是终止进程。
SIGUSR2
 
与 SIGUSR1 信号相同
SIGPIPE
 
涉及到管道和 socket,当进程向已经关闭的管道、 FIFO 或套接字写入信息时,那么系统将发送该信号给进程。该信号的系统默认操作是终止进程。
SIGALRM
 
与系统调用 alarm()或 setitimer()有关,应用程序中可以调用 alarm()或 setitimer()函数来设置一个定时器,当定时器定时时间到,那么内核将会发送 SIGALRM 信号给该应用程序该信号的系统默认操作是终止进程。
SIGTERM
 

这是用于终止进程的标准信号,也是 kill 命令所发送的默认信号(kill xxx, xxx 表示进程 pid)

注:有时我们会直接使用"kill -9 xxx"显式向进程发送 SIGKILL 信号来终止进程,然而这一做法通常是错误的,精心设计的应用程序应该会捕获 SIGTERM 信号、并为其绑定一个处理函数,当该进程收到 SIGTERM 信号时,
会在处理函数中清除临时文件以及释放其它资源,再而退出程序。

SIGCHLD
 

当父进程的某一个子进程终止时,内核会向父进程发送该信号。

当父进程的某一个子进程因收到信号而停止或恢复时,内核也可能向父进程发送该信号。

注:如果父进程希望被告知其子进程的这种状态改变,则应捕获此信号

SIGCLD与 SIGCHLD 信号同义。
SIGCONT
 
将该信号发送给已停止的进程,进程将会恢复运行。当进程接收到此信号时并不处于停止状态, 系统默认操作是忽略该信号,但如果进程处于停止状态,则系统默认操作是使该进程继续运行。
SIGSTOP
 
这是一个“必停”信号,用于停止进程,应用程序无法将该信号忽略或者捕获,故而总能停止进程。
SIGTSTP
 
这也是一个停止信号,当用户在终端按下停止字符(通常是 CTRL + Z),那么系统会将 SIGTSTP 信号发送给前台进程组中的每一个进程,使其停止运行
SIGXCPU
 
当进程的 CPU 时间超出对应的资源限制时,内核将发送此信号给该进程
SIGVTALRM
 
应用程序调用 setitimer()函数设置一个虚拟定时器,当定时器定时时间到时,内核将会发送该信号给进程。
SIGWINCH
 
在窗口环境中,当终端窗口尺寸发生变化时(譬如用户手动调整了大小,应用程序调用 ioctl()设置了大小等),系统会向前台进程组中的每一个进程发送该信号。
SIGPOLL/SIGIO
 
这两个信号同义。用于提示一个异步 IO 事件的发生,譬如应用程序打开的文件描述符发生了 I/O 事件时,内核会向应用程序发送 SIGIO 信号。
SIGSYS
 
如果进程发起的系统调用有误,那么内核将发送该信号给对应的进程。
信号名称编号描述系统默认操作
SIGINT2终端中断符term
SIGQUIT3终端退出符term+core
SIGILL4非法硬件指令term+core
SIGABRT6异常终止(abort)term+core
SIGBUS7内存访问错误term+core
SIGFPE8算术异常term+core
SIGKILL9终极终止信号term
SIGUSR110用户自定义信号 1term
SIGSEGV11无效的内存引用term+core
SIGUSR212用户自定义信号 2term
SIGPIPE13管道关闭term
SIGALRM14定时器超时(alarm)term
SIGTERM15终止进程term
SIGCHLD/SIGCLD17子进程终止或停止ignore
SIGCONT18使停止状态的进程继续运行cont
SIGSTOP19停止进程stop
SIGTSTP20终端停止符stop
SIGXCPU24超过 CPU 限制term+core
SIGVTALRM26虚拟定时器超时term
SIGWINCH28终端窗口尺寸发生变化ignore
SIGPOLL/SIGIO29异步 I/Oterm/ignore
SIGSYS31无效系统调用term+core

注: term 表示终止进程; core 表示生成核心转储文件, 核心转储文件可用于调试; ignore 表示忽略信号; cont 表示继续运行进程; stop 表示停止进程(停止不等于终止,而是暂停)。

10、signal()函数

#include <signal.h>

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

参数 signum: 此参数指定需要进行设置的信号,可使用信号名(宏)或信号的数字编号。
参数 handler: sig_t 类型的函数指针,指向信号对应的信号处理函数,当进程接收到信号后会自动执行该处理函数;参数 handler 既可以设置为用户自定义的函数,也就是捕获信号时需要执行的处理函数。sig_t 函数指针的 int 类型参数指的是,当前触发该函数的信号,可将多个信号绑定到同一个信号处理函数上,此时就可通过此参数来判断当前触发的是哪个信号。

#define SIG_ERR ((sig_t) -1)错误返回
#define SIG_DFL ((sig_t) 0)系统默认操作
#define SIG_IGN ((sig_t) 1)忽略信号

返回值: 此函数的返回值也是一个 sig_t 类型的函数指针,成功情况下的返回值则是指向在此之前的信号处理函数;如果出错则返回 SIG_ERR,并会设置 errno。

11、sigaction()函数

#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

参数 signum: 需要设置的信号,除了 SIGKILL 信号和 SIGSTOP 信号之外的任何信号。
参数 act: act 参数是一个 struct sigaction 类型指针,指向一个 struct sigaction 数据结构,该数据结构描述了信号的处理方式;如果参数 act 不为 NULL,则表示需要为信号设置新的处理方式;如
果参数 act 为 NULL,则表示无需改变信号当前的处理方式。

oldact: oldact 参数也是一个 struct sigaction 类型指针,指向一个 struct sigaction 数据结构。如果参数oldact 不为 NULL, 则会将信号之前的处理方式等信息通过参数 oldact 返回出来;如果无意获取此类信息,那么可将该参数设置为 NULL。
返回值: 成功返回 0;失败将返回-1,并设置 errno。

12、sigaction 结构体

struct sigaction {
    void (*sa_handler)(int); //指定信号处理函数,与 signal()函数的 handler 参数相同。
    void (*sa_sigaction)(int, siginfo_t *, void *); //
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_restorer)(void);
};

sa_handler:指定信号处理函数,与 signal()函数的 handler 参数相同。

sa_sigaction:也用于指定信号处理函数,这是一个替代的信号处理函数,它提供了更多的参数,可以通过该函数获取到更多信息,这些信号通过 siginfo_t 参数获取。 sa_handler 和sa_sigaction 是互斥的,不能同时设置(通过SA_SIGINFO 标志进行选择)。

sa_mask:参数 sa_mask 定义了一组信号, 当进程在执行由 sa_handler 所定义的信号处理函数之前,会先将这组信号添加到进程的信号掩码字段中,当进程执行完处理函数之后再恢复信号掩码,将这组信号从信号掩码字段中删除。 当进程在执行信号处理函数期间, 可能又收到了同样的信号或其它信号,从而打断当前信号处理函数的执行,这就好点像中断嵌套;通常我们在执行信号处理函数期间不希望被另一个信号所打断,那么怎么做呢?那么就是通过信号掩码来实现, 如果进程接收到了信号掩码中的这些信号,那么这个信号将会被阻塞暂时不能得到处理,直到这些信号从进程的信号掩码中移除。 在信号处理函数调用时,进程会自动将当前处理的信号添加到信号掩码字段中,这样保证了在处理一个给定的信号时,如果此信号再次发生,那么它将会被阻塞。如果用户还需要在阻塞其它的信号,则可以通过设置参数 sa_mask 来完成 ,信号掩码可以避免一些信号之间的竞争状态(也称为竞态)。

sa_restorer:该成员已过时,不要再使用了

sa_flags: 参数 sa_flags 指定了一组标志,这些标志用于控制信号的处理过程。

SA_NOCLDSTOP如果signum为SIGCHLD, 则子进程停止时(即当它们接收到SIGSTOP、SIGTSTP、SIGTTIN 或SIGTTOU中的一种时)或恢复(即它们接收到 SIGCONT)时不会收到 SIGCHLD 信号。
SA_NOCLDWAIT
 
如果 signum 是 SIGCHLD,则在子进程终止时不要将其转变为僵尸进程。
SA_NODEFER
 
不阻塞从某个信号自身的信号处理函数中接收此信号。 也就是说当进程此时正在执行某个信号的处理函数,默认情况下,进程会自动将该信号添加到进程的信号掩码字段中,从而在执行信号处理函数期间阻塞该信号, 默认情况下,我们期望进程在处理一个信号时阻塞同种信号,否则引起一些竞态条件;如果设置了 SA_NODEFER 标志,则表示不对它进行阻塞。
SA_RESETHAND
 
执行完信号处理函数之后,将信号的处理方式设置为系统默认操作。
SA_RESTART
 
被信号中断的系统调用,在信号处理完成之后将自动重新发起。
SA_SIGINFO
 
如果设置了该标志,则表示使用 sa_sigaction 作为信号处理函数、而不是 sa_handler。

13、siginfo_t 结构体

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_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) */
}

14、信号集

14.1、sigset_t结构体

# define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int)))
typedef struct
{
    unsigned long int __val[_SIGSET_NWORDS];
} sigset_t;

14.2、sigemptyset()函数

初始化信号集,使其不包含任何信号

#include <signal.h>
int sigemptyset(sigset_t *set);

参数 set: 指向需要进行初始化的信号集变量。
返回值: 成功返回 0;失败将返回-1,并设置 errno。

14.3、sigfillset函数

sigfillset()函数初始化信号集,使其包含所有信号。

#include <signal.h>
int sigfillset(sigset_t *set);

参数 set:指向需要进行初始化的信号集变量。

返回值: 成功返回 0;失败将返回-1,并设置 errno。

14.4、sigaddset()函数

向信号集中添加一个信号。

#include <signal.h>
int sigaddset(sigset_t *set, int signum);

参数 set: 指向信号集。
参数 signum: 需要添加的信号。
返回值: 成功返回 0;失败将返回-1,并设置 errno。

14.5、sigdelset()函数

向信号集中移除一个信号。

#include <signal.h>
int sigdelset(sigset_t *set, int signum);

参数 set: 指向信号集。

参数 signum: 需要删除的信号。
返回值: 成功返回 0;失败将返回-1,并设置 errno。

14.6、sigismember()函数

测试信号是否在信号集中。

#include <signal.h>
int sigismember(const sigset_t *set, int signum);

参数 set: 指定信号集。
参数 signum: 需要进行测试的信号。
返回值: 如果信号 signum 在信号集 set 中,则返回 1;如果不在信号集 set 中,则返回 0;失败则返回-1,并设置 errno。

15、获取信号的描述信息

在 Linux 下,每个信号都有一串与之相对应的字符串描述信息,用于对该信号进行相应的描述。

15.1、sys_siglist 数组

描述信息字符串位于 sys_siglist 数组中, sys_siglist 数组是一个 char *类型的数组,数组中的每一个元素存放的是一个字符串指针,指向一个信号描述信息(例如,可以使用 sys_siglist[SIGINT]来获取对 SIGINT 信号的描述)。

15.2、strsignal()函数

调用 strsignal()函数将会获取到参数 sig 指定的信号对应的描述信息,返回该描述信息字符串的指针;函数会对参数 sig 进行检查,若传入的 sig 无效,则会返回"Unknown signal"信息。

#include <string.h>
char *strsignal(int sig);

参数 sig:需要输出描述信息的信号。

15.3、psignal()函数

psignal()可以在标准错误(stderr)上输出信号描述信息。

#include <signal.h>
void psignal(int sig, const char *s);

参数 sig:需要输出描述信息的信号。

参数 s:允许调用者添加一些输出信息。

16、sigprocmask()函数

向信号掩码中添加/移除信号。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

参数 how: 参数 how 指定了调用函数时的一些行为。

SIG_BLOCK将参数 set 所指向的信号集内的所有信号添加到进程的信号掩码中
SIG_UNBLOCK将参数 set 指向的信号集内的所有信号从进程信号掩码中移除
SIG_SETMASK进程信号掩码直接设置为参数 set 指向的信号集。

参数 set: 将参数 set 指向的信号集内的所有信号添加到信号掩码中或者从信号掩码中移除;如果参数 set 为NULL,则表示无需对当前信号掩码作出改动。

参数 oldset: 如果参数 oldset 不为 NULL,在向信号掩码中添加新的信号之前,获取到进程当前的信号掩码,存放在 oldset 所指定的信号集中;如果为 NULL 则表示不获取当前的信号掩码。

返回值: 成功返回 0;失败将返回-1,并设置 errno。

17、sigsuspend()函数

sigsuspend()函数会将参数 mask 所指向的信号集来替换进程的信号掩码,也就是将进程的信号掩码设置为参数 mask 所指向的信号集,然后挂起进程,直到捕获到信号被唤醒(如果捕获的信号是 mask 信号集中的成员,将不会唤醒、继续挂起)并从信号处理函数返回一旦从信号处理函数返回, sigsuspend()会将进程的信号掩码恢复成调用前的值。
调用 sigsuspend()函数相当于以原子操作的方式执行以下操作:

sigprocmask(SIG_SETMASK, &mask, &old_mask);
pause();
sigprocmask(SIG_SETMASK, &old_mask, NULL);
#include <signal.h>
int sigsuspend(const sigset_t *mask);

参数 mask: 参数 mask 指向一个信号集。
返回值: 始终返回-1,并设置 errno 来指示错误(通常为 EINTR) ,表示被信号所中断,如果调用失败,将 errno 设置为 EFAULT。

18、sigpending()函数

sigpending()函数可以确定进程中哪些信号处于等待状态。

#include <signal.h>
int sigpending(sigset_t *set);

参数 set: 处于等待状态的信号会存放在参数 set 所指向的信号集中。
返回值: 成功返回 0;失败将返回-1,并设置 errno。

19、sigqueue()函数

新的发送信号系统调用,主要是针对实时信号提出的,支持信号带有参数,与函数sigaction()配合使用, sa_flags设置上SA_SIGINFO。

#include <signal.h>
int sigqueue(pid_t pid, int sig, const union sigval value);

参数 pid: 指定接收信号的进程对应的 pid,将信号发送给该进程。
参数 sig: 指定需要发送的信号。与 kill()函数一样,也可将参数 sig 设置为 0,用于检查参数 pid 所指定的进程是否存在。
参数 value: 参数 value 指定了信号的伴随数据, union sigval 数据类型。

ypedef union sigval
{
    int sival_int;
    void *sival_ptr;
} sigval_t;

返回值: 成功将返回 0;失败将返回-1,并设置 errno。

20、kill()函数

kill()系统调用可将信号发送给指定的进程或进程组中的每一个进程。

注:进程中将信号发送给另一个进程是需要权限的,并不是可以随便给任何一个进程发送信号,超级用户root 进程可以将信号发送给任何进程,但对于非超级用户(普通用户)进程来说,其基本规则是发送者进程的实际用户 ID 或有效用户 ID 必须等于接收者进程的实际用户 ID 或有效用户 ID。

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

参数 pid: 

>0信号 sig 将发送到 pid 指定的进程
=0将 sig 发送到当前进程的进程组中的每个进程
=-1将 sig 发送到当前进程有权发送信号的每个进程(1号进程init除外)
<-1将 sig 发送到 ID 为-pid 的进程组中的每个进程

参数 sig: 参数 sig 指定需要发送的信号,也可设置为 0,如果参数 sig 设置为 0 则表示不发送信号,但任执行错误检查,这通常可用于检查参数 pid 指定的进程是否存在(如果向一个不存在的进程发送信号, kill()将会返回-1, errno 将被设置为 ESRCH,表示进程不存在)。

返回值: 成功返回 0;失败将返回-1,并设置 errno。

21、raise()函数

raise()函数向自身发送信号,其等价于kill(getpid(), sig);

#include <signal.h>
int raise(int sig);

参数 sig: 需要发送的信号。
返回值: 成功返回 0;失败将返回非零值。

22、alarm()函数

使用 alarm()函数可以设置一个定时器(闹钟) ,当定时器定时时间到时,内核会向进程发送 SIGALRM信号。alarm 闹钟并不能循环触发,只能触发一次,若想要实现循环触发,可以在 SIGALRM 信号处理函数中再次调用 alarm()函数设置定时器。

#include <unistd.h>
unsigned int alarm(unsigned int seconds);

参数 seconds: 设置定时时间,以秒为单位;如果参数 seconds 等于 0,则表示取消之前设置的 alarm 闹钟。
返回值: 如果在调用 alarm()时,之前已经为该进程设置了 alarm 闹钟还没有超时,则该闹钟的剩余值作为本次 alarm()函数调用的返回值;否则返回 0。
 

23、pause()函数

pause()系统调用可以使得进程暂停运行、进入休眠状态,直到进程捕获到一个信号为止,只有执行了信号处理函数并从其返回时, pause()才返回。在这种情况下, pause()返回-1,并且将 errno 设置为 EINTR。

#include <unistd.h>
int pause(void);

24、abort()函数

调用abort()函数终止进程运行,会生成核心转储文件,可用于判断程序调用 abort()时的程序状态。函数 abort()通常产生 SIGABRT 信号来终止调用该函数的进程, SIGABRT 信号的系统默认操作是终止进程运行、并生成核心转储文件;

#include <stdlib.h>
void abort(void);

注:无论阻塞或忽略 SIGABRT 信号, abort()调用都不收到影响,总会成功终止进程。
 

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值