Linux基础:基本信号函数的使用signal等
基本概念
1、中断
当程序接收消息后中止当前正在执行的程序,转而执行其它任务,等其它任务执行完成后再返回,这种执行模式叫中断,分为硬件中断和软件中断。
2、信号
是一种软件中断,由操作系统发出,程序接收后会执行相应的操作。
3、常见信号
kill -l 显示所有信号
SIGINT Ctrl+c 终止
SIGQUIT Ctrl+\ 终止+core
SIGFPE 除0 终止+core
SIGSEGV 非常内存访问 终止+core
SIGKILL 终止信号 终止
4、不可靠信号和可靠信号
建立在早期的信号处理机制上(1~31) 是不可靠信号。
不支持排除,可能会丢失,同一个信号如果连续产生多次,进程可能只接收到一次。
建立在新信号处理机制上 (34~64) 是可靠信号,支持排除,不会丢失。
5、信号来源
硬件异常:除0、无效内存访问、未定义指令、总线错误、软件异常。 软件异常:通过一些命令、函数产生的信号。
6、信号的处理方式
1、忽略 2、终止进程 3、终止进程并产生core文件 4、捕获并处理(当信号发前,向内核注册一个函数, 当信号发生时系统自动执行该函数)。
信号捕获:
typedef void (*sighandler_t)(int); 功能:信号处理函数的格式 sighandler_t signal(int signum, sighandler_t handler); 功能:向信号注册一个信号处理函数 signum:信号编号 handler:函数指针 SIG_IGN 忽略 SIG_DFL 按默认处理 返回值: 之前的信号处理方式
注意:
(1)有些系统通过signal注册的函数只执行一次,如果想持续有效,可以在信号处理函数中再注册一次。
(2)子进程会继承父进程的信号处理方式,但如果是通过exec系列函数创建的子进程,会恢复默认的信号处理式。
(3)信号处理完后会返回到产生信号的代码处理,如果我们捕获并处理段错误或算术异常可能会产生死循环,正确处理段错误和算术异常应该是备份数据并结束进程。
信号的发送:
键盘: Ctrl+c Ctrl+\ Ctrl+z 错误: 除0 非法内存访问 硬件故障 总线错误 命令: kill 信号 进程号 killall 信号 进程名 函数: int kill(pid_t pid, int sig); 功能:向指定的进程发送信号 int raise(int sig); 功能:向进程自己发送信号 void abort(void); 功能:向进程自己发送SIGABRT信号 unsigned int alarm(unsigned int seconds); 功能:让内核在seconds后向进程发关这SIGALRM信号 返回值:上次alarm设置的剩余时间 注意:如果再次调用会覆盖之前的设置,而不会产生两次闹钟信号。
进程休眠与信号:
int pause(void); 功能:让调用者进入休眠状态,直接进程遇到信号(捕获处理、进程结束) 返回值:要么一直休眠不返回,要么返回-1。 相当于没有时间限制的sleep unsigned int sleep(unsigned int seconds); 功能:让调用者进入休眠指定的秒数,当遇到信号时会提前返回。 返回值:剩余的休眠时间
信号集与信号阻塞:
信号集:是一种数据类型,可以存储多个信号。 sigset_t 128二进制,每一次都代码一个信号。 相关函数: int sigemptyset(sigset_t *set); 功能:清空信号集 int sigfillset(sigset_t *set); 功能:填满信号集 int sigaddset(sigset_t *set, int signum); 功能:向信号集中添加信号 int sigdelset(sigset_t *set, int signum); 功能:从信号集中删除信号 int sigismember(const sigset_t *set, int signum); 功能:测试信号集中是否有某个信号 功能: 0 不存在 1 存在 -1 信号非法
信号阻塞:
当程序在执行一些特殊操作时是不适合处理信号的,此时可以让内核先屏蔽信号,等操作执行完成后再发送信号。
当信号产生时,内核会在其所维护信号表中为进程设置一个与该信号对应的标记,这个过程叫递送。
从信号产生到完成递送有个时间间隔,处于这个间隔的信号状态叫未决。
信号屏蔽就是让信号先处于未决状态,暂停递送,当屏蔽解除时再继续递送。
每个进程都有一个信号集用于存储要屏蔽的信号。
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
功能:设置要屏蔽的信号,这些信号存储在信号集里面。
how:
SIG_BLOCK 把set中的信号添加到要屏蔽的信号集里。
SIG_UNBLOCK 从信号集删除set的信号。
SIG_SETMASK 用set替换之前的信号集。
set:准备好的信号集
oldset:获取的信号的集
int sigpending(sigset_t *set);
功能:获取未决状态的信号
带附加的信号处理:
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
功能:向内核注册一个信号处理方式
signum:要捕获的信号
act:信号处理函数
oldact:获取旧的信号处理式
struct sigaction { void (*sa_handler)(int); // 不带附加数据信号处理函数 void (*sa_sigaction)(int, siginfo_t *, void *); //带附加数据信号处理函数 sigset_t sa_mask; // 信号屏蔽信 在信号函数函数执行过程中,默认屏蔽当前信号,如果想屏蔽其它信号可以向sa_mask中添加。 int sa_flags; // 信号处理标志 SA_NOCLDSTOP 如果signum是SIGCHLD,则子进程停止时不要向我发送SIGCHLD。 SA_NOCLDWAIT 如果signum是SIGCHLD,则子进程结束时不要产生僵尸进程。 SA_NODEFER 在信号处理过程中不要屏蔽当前信号。 SA_RESETHAND 该信号处理方式执行完成后,还原成默认的处理方式。 SA_RESTART 系统调用一旦被信号打断,自动重启。 SA_SIGINFO 使用函数指针2,处理信号 void (*sa_restorer)(void); // 保留,NULL }; 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 kernel 2.6.32) */ int sigqueue(pid_t pid, int sig, const union sigval value); 功能:向指定的进程发送信号并附加信号 union sigval { int sival_int; // 整数 void *sival_ptr; // 指针 };
定时器:
int getitimer(int which, struct itimerval *curr_value);
功能:获取当前的定时方案
which:
ITIMER_REAL 真实计时器,程序总的运行时间 SIGALRM
ITIMER_VIRTUAL 虚拟计时器 用户态的运行时间 SIGALRM
ITIMER_PROF 实际计时器 用户态+内核态的运行时间 SIGPROF
真实计时器 = 实际计时器 + 休眠时间
int setitimer(int which, const struct itimerval *new_value,
struct itimerval *old_value);
功能:设置新的定义方案
struct itimerval { struct timeval it_interval; /* next value */ 每次时钟信号产生和间隔时间 struct timeval it_value; /* current value */ 第一次时钟信号产生和时间 }; struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */ };
- 【linux基础】15、LVM基本使用
- Linux基础-命令的基本使用
- Linux基础(三)--grep的使用和基本正则表达式
- linux基础(2)--服务器组装和基本命令使用--RHEL6.5
- linux下mysql基础从安装到基本使用
- linux基础和vim基本使用
- Linux基础命令以及VIM文本编辑器的基本使用
- python基础之Linux系统的基本使用
- Linux基础:vi/vim编辑器的基本使用
- Linux基础(Vi基本使用)
- Python基础学习笔记 05、06(Linux基本使用)
- linux下使用rpm安装libxml2,gcc,gcc-c++等基本包
- 2.linux驱动基础开发1——linux 设备驱动基本概念
- OpenGL基础图形编程 - OpenGL辅助库的基本使用
- 刘道军老师 RHCE 033系列第2讲 Linux使用基础
- linux基础学习之mount的基本用法
- linux——vi编辑器基本使用方法
- Linux Signal (1): 基本概念
- Linux下使用Vim进行C/C++ 编程基础知识详解
- [Linux学习笔记]第1天:操作系统的发展史,linux诞生,Linux发行商,shell,terminal,shell使用技巧,文件目录,基本操作