目录
目标:
实战:
Linux中的信号
信号的基本操作
相关函数
信号集合操作
未决信号
如何发起异步操作(对本身发起,对其他进程发起)
如何安装信号
如何屏蔽和管理信息
如何利用信号进行阻塞操作
信号驱动的服务器
电报机
信号 取值 默认动作 含义(发出信号的原因)
SIGHUP 1 Term 终端的挂断或进程死亡
SIGINT 2 Term 来自键盘的中断信号
SIGQUIT 3 Core 来自键盘的离开信号
SIGILL 4 Core 非法指令
SIGABRT 6 Core 来自abort的异常信号
SIGFPE 8 Core 浮点例外
SIGKILL 9 Term 杀死
SIGSEGV 11 Core 段非法错误(内存引用无效)
SIGPIPE 13 Term 管道损坏:向一个没有读进程的管道写数据
SIGALRM 14 Term 来自alarm的计时器到时信号
SIGTERM 15 Term 终止
SIGUSR1 30,10,16 Term 用户自定义信号1
SIGUSR2 31,12,17 Term 用户自定义信号2
SIGCHLD 20,17,18 Ign 子进程停止或终止
SIGCONT 19,18,25 Cont 如果停止,继续执行
SIGSTOP 17,19,23 Stop 非来自终端的停止信号
SIGTSTP 18,20,24 Stop 来自终端的停止信号
SIGTTIN 21,21,26 Stop 后台进程读终端
SIGTTOU 22,22,27 Stop 后台进程写终端
SIGBUS 10,7,10 Core 总线错误(内存访问错误)
SIGPOLL Term Pollable事件发生(Sys V),与SIGIO同义
SIGPROF 27,27,29 Term 统计分布图用计时器到时
SIGSYS 12,-,12 Core 非法系统调用(SVr4)
SIGTRAP 5 Core 跟踪/断点自陷
SIGURG 16,23,21 Ign socket紧急信号(4.2BSD)
SIGVTALRM 26,26,28 Term 虚拟计时器到时(4.2BSD)
SIGXCPU 24,24,30 Core 超过CPU时限(4.2BSD)
SIGXFSZ 25,25,31 Core 超过文件长度限制(4.2BSD)
SIGIOT 6 Core IOT自陷,与SIGABRT同义
SIGEMT 7,-,7 Term
SIGSTKFLT -,16,- Term 协处理器堆栈错误(不使用)
SIGIO 23,29,22 Term 描述符上可以进行I/O操作
SIGCLD -,-,18 Ign 与SIGCHLD同义
SIGPWR 29,30,19 Term 电力故障(System V)
SIGINFO 29,-,- 与SIGPWR同义
SIGLOST -,-,- Term 文件锁丢失
SIGWINCH 28,28,20 Ign 窗口大小改变(4.3BSD, Sun)
SIGUNUSED -,31,- Term 未使用信号(will be SIGSYS)
发送信号 kill -x pid 函数:int kill(pid,signum)
捕获信号 signal(signum,函数)== SIG_ERR
忽略信号 signal(signum,SIG_IGN)
pause()使调用进程(或线程)进入休眠状态,直到传递的信号终止进程或导致调用信号捕获函数。
alarm(4)定时器,4s后返回 重复使用会让上一个定时器返回,返回内容是剩余时间 发送SIGALRM信号
ualarm(5000000,2000000) 第一5s返回 之后2s返回一次 发送SIGALRM信号(注:该函数多次实验,均未成功)
int getitimer(int which,struct itimerval * curr_value);
int setitimer(int which,const struct itimerval * new_value,struct itimerval(old_value);
ITIMER_REAL 根据系统时间递减
ITIMER_VIRTUAL 根据程序执行时间递减
ITIMER_PROG 进程执行,系统调用的时候才递减
struct itimerval
{struct itmerval it_interval //间隔值
struct itmerval in_value //第一次值}
struct itmerval
{time_t tv_sec; s单位
suseconds_t tv_usec ; mincroseconds 微秒为单位}
int sigaction(int signum,const struct sigaction *act,struct sigaction *oldact);
struct sigaction
void (*sa_handler)(int) 和参数2 二选一
void (*sa_sigaction)(int ,siginfo_t *,void *);
sigset_t sa_mask; 信号屏蔽集合
//清空信号sigemptyset(&act.sa_mask);添加sigaddset(&s,SIGUSR1);sigfillset
int sa_flags; 接受标志 //接收数据时 需要设置sa_flags = SA_SIGINFO
void (*sa_restorer)(void);
sigset_t 信号集合
SA_SIGINFO
siginfo_t{
int si_signo 信号number
int si_errno 错误值
int si_code
int si_trapno}
pid si_pid
........
union sigval_t {
int sival_int;
void * sival_ptr}
sigqueue(pid,signum,union sigval aaa)发送信号到指定pid 并且传递一个参数
int sigemptyset(sigset_t *set);
int sigfillset (sigset *set);
int sigaddset(sigset *set,int signum);
int sigdelset(sigset *set,int signum);
int sigismember(const sigset_t *set,int signum); 判断是否存在
设置屏蔽信号集合
int sigprocmask(int how,const sigset_t *set,sigse_t *oldset);设置set为屏蔽信号
SIG_BLOCK设置信号阻塞方式 SIG_UNBLOCK非阻塞 SIG_SETMASK设置为屏蔽集
sigpending(sigset *set);
//查看未决信号中有哪些信号
void print_sig(sigset_t *p)
{
int i=1;
for(;i<32;i++){
if(sigismenmber(p,i)){
printf("1");
}else {
printf("0");
}
}
printf("\n");
}
sigsuspend(strcut sigset_t *set) 等待信号函数 接收到一个信号 不在set中 该函数返回
简单例子:
#include "stdio.h"
#include
#include "signal.h"
#include "errno.h"
#include
#include
#include
#include
union sigval val;
pid_t pid;
void showprogress(int a, siginfo_t * info, void * data){
printf("file copy progress:%d\n", info->si_value.sival_int);
if((info->si_value.sival_int) >1000)
{
printf("file copy sucess!!!\n");
exit(0);
}
}
void sendsigusr1(int pro)
{
union sigval haha;
haha.sival_int =100;
val.sival_int = 100;
sigqueue(pid,SIGUSR1,haha);
}
int main(int argc,char*argv[])
{
int readfile,writfile;
int filesize = 0;
if(argc<3)
{
printf("please stdin enter file name : readfile writfile...");
exit(0);
}
pid = fork();
if(pid==-1){
perror("fork error");
exit(0);
}else if(pid == 0)
{
struct sigaction act;
printf("haha\n");
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = showprogress;
sigemptyset(&(act.sa_mask));
sigaction(SIGUSR1,&act,NULL);
while(1){
printf("chlid is runing!\n");
pause();
}
}else if(pid>0){
int progress = 0;
int i = 0;
char buf[8];
val.sival_int = 0;
if((readfile = open(argv[1],O_RDWR))==-1)
{
perror("open");
exit(0);
}
if ((writfile = open(argv[2],O_RDWR|O_CREAT))==-1)
{
/* code */perror("open");
exit(0);
}
filesize = lseek(readfile,0,SEEK_END);
lseek(readfile,0,SEEK_SET);
signal(SIGALRM,sendsigusr1);
//ualarm(1,1);
while(1)
{
i = read(readfile,buf,1);
if(i <=0) {
close(readfile);
close(writfile);
break;
}
progress+=i;
write(writfile,buf,1);
val.sival_int = progress;
sigqueue(pid,SIGUSR1,val);
}
close(readfile);
close(writfile);
val.sival_int = -666;
sigqueue(pid,SIGUSR1,val);
}
}