您现在的位置: 首页 > 网站导航收录 > 百科知识百科知识
remian remained
信号,函数,进程remian remained
发布时间:2020-12-06加入收藏来源:互联网点击:
很多朋友想了解关于remian的一些资料信息,下面是小编整理的与remian相关的内容分享给大家,一起来看看吧。
信号是系统响应某些条件而产生的一个事件,接收到该信的进程做出相应的处理。通常信是由错误产生的,如段错误(SIGSEGV)。 但信还可以作为进程间通信的一种方式,由一个进程发送给另一个进程。
信号定义在 signal.h 文件中,以 SIG 作为开头,可用 kill -l 命令查看,详细信息参见 man 7 signal。
信号处理信号可以通过 signal 和 sigaction 函数来注册处理, signal 函数是 struct sigaction 中 sa_handler 的一种便捷实现。
signal 函数原型:
void (*signal(int sig, void (*func)(int)))(int);其中 sig 是需要捕获的 signal number, 后一个是捕获到信号后的处理函数指针,所以处理函数的原型必须是 void func(int) ,简单的代码示例如下:
#include stdio.h#include string.h#include signal.hstatic voidhandler(int sig){ printf("Recieved signal: %d\n", sig);}intmain(int argc, char *argv[]){ signal(SIGINT, handler); printf("Caught SIGINT, input 'quit' to exit...\n"); // wait signal caught char buf[1024] = {0}; while (1) { printf("Please input: "); scanf("%s", buf); if (strcmp(buf, "quit") == 0) { break; } } printf("Exit...\n"); return 0;}另外 api 中也提供了下面 2 个特殊的 handler:
SIG_IGN忽略此信号
SIG_DFL恢复此信号的默认行为
sigaction 函数原型:
int sigaction(int sig, const struct sigaction *restrict act, struct sigaction *restrict oact);其中 sig 为 signal number, act 指定信号的处理行为, oact 如果不为 NULL 则返回信号之前的处理行为。
struct sigaction 的主要成员如下:
void(*) (int) sa_handler 处理函数指针,同 signal 函数中的 func 参数sigset_t sa_mask 信号屏蔽字,是指当前被阻塞的一组信号,不能被当前进程收到int sa_flags 处理行为修改器,指明哪种处理函数生效,详见下文void(*) (int, siginfo_t *, void *) sa_sigaction 处理函数指针,仅 sa_flags == SA_SIGINFO 时有效 其中 sa_flags 主要可以设置为以下值:SA_NOCLDSTOP子进程停止时不产生 SIGCHLD 信号
SA_RESETHAND将信号的处理函数在处理函数的入口重置为 SIG_DFL
SA_RESTART重启可中断的函数而不是给出 EINTR 错误
SA_SIGINFO使用 sa_sigaction 做为信号的处理函数
SA_NODEFER捕获到信号时不将它添加到信号屏蔽字中
简单的代码示例如下:
#include stdio.h#include string.h#include signal.h#define SIG SIGINTstatic voidsig_handler(int sig, siginfo_t *si, void *data){ printf("Caught signal: %d\n", sig); printf("Sender pid: %d\n", si-si_pid); printf("Sender uid: %d\n", si-si_uid);}static intsig_caught(int sig){ printf("Start caught signal: %d\n", sig); struct sigaction sa; sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = sig_handler; sigemptyset(sa.sa_mask); int ret = sigaction(sig, sa, NULL); if (ret == -1) { printf("Failed to caught signal: %d\n", sig); return -1; } return 0;}intmain(int argc, char *argv[]){ if (sig_caught(SIG) == -1) { return -1; } printf("Caught signal(%d), input 'quit' to exit...\n", SIG); char buf[1024] = {0}; while(1) { printf("Please input: "); scanf("%s", buf); if (strcmp(buf, "quit") == 0) { break; } } printf("Exit...\n"); return 0;}信号屏蔽字考虑一下这种情况:在 signal()/sigaction() 返回之前进程就已经收到了需要处理的信号,此时进程会以默认行为来处理,这显然不符合我们的期望。 这时就需要用到信号屏蔽字了,在进程启动时就将需要处理的信号加入的屏蔽字中,等 signal()/sigaction() 返回后再解除屏蔽,解除屏蔽后至少会将收到的待处理信号发送一个给进程。
屏蔽字用到一下函数:
int sigemptyset(sigset_t *set);int sigaddset(sigset_t *set, int signo);int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);sigprocmask 中 set 为需要设置的屏蔽字集, oset 为之前的屏蔽字集, how 控制着 set 如何生效,可设置为以下值:
SIG_BLOCK该进程的屏蔽字集将为当期屏蔽字集与 set 的并集, set 中包含了需要屏蔽的信号集
SIG_UNBLOCK该进程的屏蔽字集将为当期屏蔽字集与 set 的补集的交集, set 中包含了需要解除屏蔽的信号集
SIG_SETMASK该进程的屏蔽字集将设置为 set 的值
简单的设置流程如下:
intsig_block(int sig, int how){ sigset_t mask; sigemptyset(mask) sigaddset(mask, sig); sigprocmask(how, mask, NULL);}信号发送信号可以通过 kill 函数发送给指定进程,也可以通过 raise 或者 alarm 函数发送给当前执行的线程或进程,下面来分别说说这几个函数。
kill 函数原型:
int kill(pid_t pid, int sig);kill 函数向指定进程发送指定的信号,如果信号为 0 将执行错误检查,信号并不会发送,可以用来检查 pid 的有效。
pid 大于 0 时信号将发送给此进程, pid 小于等于 0 时,如下:
等于 0信号将发送给发送者所在组里的所有进程
等于 -1信号将发送给所有进程
小于 -1信号将发送给进程组为 pid 绝对值的所有组内进程
alarm 函数原型:
unsigned alarm(unsigned seconds);alarm 函数将在指定的 seconds 之后发送一个 SIGALRM 信号,如果 seconds 为 0, 则取消之前的定时器请求。如果不为 0 则取消之前的请求,重新设置为 seconds 。 如果在等待结束之前有其他的事件产生,那定时器请求也将被取消。
简单的代码示例如下:
#include stdio.h#include unistd.h#include signal.hstatic voidhandler(int sig){ printf("alarm arrived: %d\n", sig);}intmain(int argc, char *argv[]){ signal(SIGALRM, handler); alarm(2); sleep(2); printf("alarm 5s over\n"); alarm(10); sleep(1); unsigned int remaining = alarm(3); printf("alarm 10s remain: %u, reset to 3\n", remaining); sleep(3); printf("alarm 3s over\n"); alarm(20); sleep(3); remaining = alarm(0); printf("cancel alarm 20s, remian: %u, exit...\n", remaining);}raise 函数原型:
int raise(int sig);raise 函数将给当前执行的线程或进程发送信号,如果信号处理函数已经被调用, raise 函数将等待信号处理函数调用结束才返回。
结语信号处理函数是会被重复调用的,所以必要保存其是可重入的,注意处理逻辑。
另外本文中的代码都在 https://github.com/jouyouyun/examples/tree/master/signal 中,这个 repo 也有其它的示例,有兴趣的可以看看。
附录信号表
/* ISO C99 signals. */#define SIGINT 2 /* Interactive attention signal. */#define SIGILL 4 /* Illegal instruction. */#define SIGABRT 6 /* Abnormal termination. */#define SIGFPE 8 /* Erroneous arithmetic operation. */#define SIGSEGV 11 /* Invalid access to storage. */#define SIGTERM 15 /* Termination request. *//* Historical signals specified by POSIX. */#define SIGHUP 1 /* Hangup. */#define SIGQUIT 3 /* Quit. */#define SIGTRAP 5 /* Trace/breakpoint trap. */#define SIGKILL 9 /* Killed. */#define SIGBUS 10 /* Bus error. */#define SIGSYS 12 /* Bad system call. */#define SIGPIPE 13 /* Broken pipe. */#define SIGALRM 14 /* Alarm clock. *//* New(er) POSIX signals (1003.1-2008, 1003.1-2013). */#define SIGURG 16 /* Urgent data is available at a socket. */#define SIGSTOP 17 /* Stop, unblockable. */#define SIGTSTP 18 /* Keyboard stop. */#define SIGCONT 19 /* Continue. */#define SIGCHLD 20 /* Child terminated or stopped. */#define SIGTTIN 21 /* Background read from control terminal. */#define SIGTTOU 22 /* Background write to control terminal. */#define SIGPOLL 23 /* Pollable event occurred (System V). */#define SIGXCPU 24 /* CPU time limit exceeded. */#define SIGXFSZ 25 /* File size limit exceeded. */#define SIGVTALRM 26 /* Virtual timer expired. */#define SIGPROF 27 /* Profiling timer expired. */#define SIGUSR1 30 /* User-defined signal 1. */#define SIGUSR2 31 /* User-defined signal 2. *//* Nonstandard signals found in all modern POSIX systems (including both BSD and Linux). */#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). *//* Archaic names for compatibility. */#define SIGIO SIGPOLL /* I/O now possible (4.2 BSD). */#define SIGIOT SIGABRT /* IOT instruction, abort() on a PDP-11. */#define SIGCLD SIGCHLD /* Old System V name *//* Not all systems support real-time signals. bits/signum.h indicates that they are supported by overriding __SIGRTMAX to a value greater than __SIGRTMIN. These constants give the kernel-level hard limits, but some real-time signals may be used internally by glibc. Do not use these constants in application code; use SIGRTMIN and SIGRTMAX (defined in signal.h) instead. */#define __SIGRTMIN 32#define __SIGRTMAX __SIGRTMIN/* Biggest signal number + 1 (including real-time signals). */#define _NSIG (__SIGRTMAX + 1)上一篇:有理化因式-有理化因式例题
下一篇:返回列表
相关链接 |
||
网友回复(共有 0 条回复) |