linux 大复习 信号专题
信号 专题
信号是UNIX系统响应某些状况而产生的事件,进程在接收到信号时会采取相应的行动。
信号是因为某些错误条件而产生的,比如内存段冲突、浮点处理器错误或者非法指令等
信号是在软件层次上对中断的一种模拟,所以通常把它称为是软中断
#include <sys/types.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <unistd.h> #include <sys/wait.h> void handler(int signal) { printf("this is signal %d\n",signal); } int main1() { if( signal(SIGINT,&handler) ==SIG_ERR) { perror("signal errno"); exit(1); } pid_t pid = fork(); if(pid ==0) { printf(" come on baby \n"); raise(SIGKILL); printf(" come on baby \n"); while(1); } else if(pid > 0) { /* kill(pid,SIGINT); printf("mei si ? \n"); kill(pid,SIGKILL); printf("mei si 2 ? \n"); */ } else { perror("fork erno "); exit(0); } return 0; } void handler2 (int n , siginfo_t * pinfo , void * arg) { printf("father recive : %d\n",n); union sigval value=pinfo->si_value; printf("father recive : %d\n",value.sival_int); raise(SIGKILL); return ; } /* 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 handler3 (int n , siginfo_t * pinfo , void * arg) { printf("child recive : %d\n",n); // pid_t pid = pinfo->si_pid; printf("child recive : %d\n",pinfo->si_signo); union sigval value; value.sival_int = (pinfo->si_value).sival_int ; printf("child recive date : %d\n",value.sival_int); sigqueue(getppid(), SIGUSR2, value ); raise(SIGKILL); return ; } int main() { pid_t pid = fork(); if(pid ==0) { printf(" come on baby \n"); struct sigaction act,oldact; sigemptyset(&act.sa_mask); act.sa_flags=SA_SIGINFO; act.sa_sigaction =& handler3 ; sigaction(SIGUSR1, &act,NULL); printf(" come on baby \n"); // perror("the errno "); while(1); } else if(pid > 0) { struct sigaction act,oldact ; act.sa_flags=SA_SIGINFO ; act.sa_sigaction = & handler2; sigemptyset(&act.sa_mask); sigaction(SIGUSR2,&act ,&oldact); // printf("i have sigaction SIGUSR1 \n"); union sigval value ; value.sival_int = 1000; usleep(5000); sigqueue( pid,SIGUSR1, value); usleep(5000); usleep(5000); // perror("the errno "); while(1); } else { perror("fork erno "); exit(0); } }
2.不能被忽略的信号 9 /19
9 号信号 终止进程
19 暂停进程 并中止
3.信号捕获过程
1.产生信号 2.潜入内核先处理信号,3.着看是否为用户自定义信号4.回到用户态处理信号回调,5.潜入内核继续执行,6回到用户主进程继续
4. alarm函数 默认中止进程
5.信号附带数据
只是结构体不好找,借用师傅那句话,没有多少料
sigaction 注册信号 sigqueue 发送信号
typedef struct siginfo_t{
int si_signo;//信号编号 int si_errno;//如果为非零值则错误代码与之关联 int si_code;//说明进程如何接收信号以及从何处收到
pid_t si_pid;//适用于SIGCHLD,代表被终止进程的PID
pid_t si_uid;//适用于SIGCHLD,代表被终止进程所拥有进程的UID int si_status;//适用于SIGCHLD,代表被终止进程的状态
clock_t si_utime;//适用于SIGCHLD,代表被终止进程所消耗的用户时间
clock_t si_stime;//适用于SIGCHLD,代表被终止进程所消耗系统的时间 sigval_t si_value;
int si_int;
void * si_ptr;
void* si_addr;
int si_band;
int si_fd;
};
数据 携带 联合体
union sigval {
int sival_int;
void *sival_ptr;
}
6.实时信号 非实时信号
实时信号在进程阻塞该信号的时间内,发给该进程的所有实时信号会排队,
而非实时信号则会合并为一个信号。
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> #include <errno.h> #define excite(aaaaa)perror("aaaaa");\ exit(0) void handle(int signum, siginfo_t * st , void * arg ) { if(signum== SIGUSR1) { //解除阻塞 sigset_t bset; sigemptyset(&bset); sigaddset(&bset,SIGINT); sigaddset(&bset,SIGRTMIN); sigprocmask(SIG_UNBLOCK, &bset, NULL); } else if(signum== SIGINT || signum== SIGRTMIN ) { printf("%d signal %d information \n",signum,st->si_value.sival_int); } else { } } int main() { //注册信号 printf("sssssssssssssss\n"); struct sigaction act; act.sa_sigaction =&handle ; sigemptyset(&act.sa_mask); act.sa_flags =SA_SIGINFO ; if(sigaction(SIGINT, &act,NULL) ==-1) { excite(sigaction); } if(sigaction(SIGUSR1, &act,NULL) ==-1) { excite(sigaction); } if(sigaction(SIGRTMIN, &act,NULL) ==-1) { excite(sigaction); } printf("sssssssssssssss"); //设置阻塞 sigset_t bset ; sigemptyset(&bset); sigaddset(&bset,SIGINT); sigaddset(&bset, SIGRTMIN); sigprocmask(SIG_BLOCK,&bset, NULL); pid_t cpid = fork(); if (cpid == -1) { perror("fork"); exit(0); } if (cpid == 0) { // 发送信号 union sigval value ; value.sival_int = 10; int ret ; for(int i=0;i<10;i++) { value.sival_int++; ret = sigqueue( getppid(),SIGINT, value); if(ret == 0) { printf("sennd SIGINT %d ok \n",i); } else printf("sennd SIGINT %d err \n",i); } value.sival_int =100; for(int i=0;i<10;i++) { value.sival_int++; ret = sigqueue( getppid(),SIGRTMIN, value); if(ret == 0) { printf("sennd SIGRTMIN %d ok \n",i); } else printf("sennd SIGRTMIN %d err \n",i); } usleep(100); kill(getppid(), SIGUSR1); } while(1) sleep(1); }
信号问题
1) SIGHUP:当用户退出shell时,由该shell启动的所有进程将收到这个信号,默认动作为终止进程 2)SIGINT:当用户按下了<Ctrl+C>组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号。默认动作为终止里程。3)SIGQUIT:当用户按<ctrl+\>组合键时产生该信号,用户终端向正在运行中的由该终端启动的程序发出些信号。默认动作为终止进程。 4)SIGILL:CPU检测到某进程执行了非法指令。默认动作为终止进程并产生core文件 5)SIGTRAP:该信号由断点指令或其他trap指令产生。默认动作为终止里程并产生core文件。 6 ) SIGABRT:调用abort函数时产生该信号。默认动作为终止进程并产生core文件。 7)SIGBUS:非法访问内存地址,包括内存对齐出错,默认动作为终止进程并产生core文件。 8)SIGFPE:在发生致命的运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为0等所有的算法错误。默认动作为终止进程并产生core文件。 9)SIGKILL:无条件终止进程。本信号不能被忽略,处理和阻塞。默认动作为终止进程。它向系统管理员提供了可以杀死任何进程的方法。 10)SIGUSE1:用户定义的信号。即程序员可以在程序中定义并使用该信号。默认动作为终止进程。 11)SIGSEGV:指示进程进行了无效内存访问。默认动作为终止进程并产生core文件。 12)SIGUSR2:这是另外一个用户自定义信号,程序员可以在程序中定义并使用该信号。默认动作为终止进程。1 13)SIGPIPE:Broken pipe向一个没有读端的管道写数据。默认动作为终止进程。 14) SIGALRM:定时器超时,超时的时间由系统调用alarm设置。默认动作为终止进程。 15)SIGTERM:程序结束信号,与SIGKILL不同的是,该信号可以被阻塞和终止。通常用来要示程序正常退出。执行shell命令Kill时,缺省产生这个信号。默认动作为终止进程。 16)SIGCHLD:子进程结束时,父进程会收到这个信号。默认动作为忽略这个信号。 17)SIGCONT:停止进程的执行。信号不能被忽略,处理和阻塞。默认动作为终止进程。 18)SIGTTIN:后台进程读终端控制台。默认动作为暂停进程。 19)SIGTSTP:停止进程的运行。按下<ctrl+z>组合键时发出这个信号。默认动作为暂停进程。 21)SIGTTOU:该信号类似于SIGTTIN,在后台进程要向终端输出数据时发生。默认动作为暂停进程。 22)SIGURG:套接字上有紧急数据时,向当前正在运行的进程发出些信号,报告有紧急数据到达。如网络带外数据到达,默认动作为忽略该信号。 23)SIGXFSZ:进程执行时间超过了分配给该进程的CPU时间,系统产生该信号并发送给该进程。默认动作为终止进程。 24)SIGXFSZ:超过文件的最大长度设置。默认动作为终止进程。 25)SIGVTALRM:虚拟时钟超时时产生该信号。类似于SIGALRM,但是该信号只计算该进程占用CPU的使用时间。默认动作为终止进程。 26)SGIPROF:类似于SIGVTALRM,它不公包括该进程占用CPU时间还包括执行系统调用时间。默认动作为终止进程。 27)SIGWINCH:窗口变化大小时发出。默认动作为忽略该信号。 28)SIGIO:此信号向进程指示发出了一个异步IO事件。默认动作为忽略。 29)SIGPWR:关机。默认动作为终止进程。 30)SIGSYS:无效的系统调用。默认动作为终止进程并产生core文件。 31)SIGRTMIN~(64)SIGRTMAX:LINUX的实时信号,它们没有固定的含义(可以由用户自定义)。所有的实时信号的默认动作都为终止进程。 1) SIGHUP:当用户退出shell
不摸着石头过河,难道要在温柔乡睡到天昏地暗。