标签:
typedef void(*sighandler_t)(int) =====》 xxx 就是 void xxx(int y) 的函数指针 入口地址
sighandler_t signal(int signum,sighandler_t handler) =====》void (*signal(int signum , (void *))(int)))(int)
handler就是函数的入口地址
/*
#include<signal.h>
作用:注册信号的行为
参数1:信号类型
参数2:信号行为:SIG_IGN(忽略这个信号) 或者SIG_DFL(默认) ,或者执行行为handler
说白点就是:当参数1 :signum来了,我就执行参数2 :执行这个行为handler
返回值:信号之前的行为
*/
eg:信号的行为是 func
sighandler_t signal(int signum,sighandler_t handler) 那么信号行为= void(*signal(int signum , void (*func)(int)))(int);//红色代表信号类型 粉色信号的行为,蓝色代表返回值是信号之前的行为。
因为C语言名空间管理不善,要用sighandler_t 必须要先typedef void(*sighandler_t)(int),如果其他的头文件也用了sighandler_t,那么函数就冲突了 ,所以要用void(*signal(int signum , void (*func)(int)))(int);
signal()使用代码:
ps: ctrl+c == SIGINT 信号:终止一个进程
一:下面函数正常情况下会1s打印一个*,如果输入ctrl+c 那么程序终止。
//此函数用于测试ctrl+c 用于终止一个进程 #include <stdio.h> #include <stdlib.h> #include <signal.h> int main() { int i ; for(i = 0 ; i < 10 ; i++)//1s打印一个星号 { write(1,"*",1); sleep(1); } exit(0); }
二:下面函数正常情况下会1s打印一个“*”,如果输入ctrl+c 那么程序忽略SIGINT信号,继续打印“*”
//此函数使用ctrl+c 函数忽略这个信号,继续打印"*" #include <stdio.h> #include <stdlib.h> #include <signal.h> int main() { int i ; signal(SIGINT,SIG_IGN); for(i = 0 ; i < 10 ; i++)//1s打印一个星号 { write(1,"*",1); sleep(1); } exit(0); }
三:将信号的行为设置为打印一个“!”替换默认行为终止一个进程
#include <stdio.h> #include <stdlib.h> #include <signal.h> static void sig_handler(int s) { write(1,"!",1); } int main() { int i ; /*在程序未结束的情况下,信号来了才执行*/ signal(SIGINT,sig_handler);//函数的入口地址:sig_handler for(i = 0 ; i < 10 ; i++)//1s打印一个星号 { write(1,"*",1); sleep(1); } exit(0); }
程序三问题:如果在程序执行的过程中,不断的使用ctrl+c, 会发现“*”还没有输出10次,程序就终止了:那么问题来了????什么问题呢?非常重要的知识点:信号会打断阻塞的系统调用
欢迎登场:信号会打断阻塞的系统调用
1.man 2 open or man 2 read and so on
//open read 是系统调用的,对吧?
2.查看函数手册return value ---->EINTR :这么说的: 当你打开一个比较慢的设备的时候,那么这个可能会被一个信号打断;
3.解决方法:当使用系统调用出错时,要判断是不是EINTR, 是:可以继续咯 ;不是: sorry,是真的错了,你就承认吧
四:实现文件copy 里面使用了系统调用函数 open so 。。。。。是不是应该加上EINTR信号的判断,以避免程序枉死!
/*利用系统调用实现文件拷贝*/ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #define BUFSIZE 1024 int main(int argc,char **argv) { int sfd,dfd;//原文件的fd ,目标文件的fd char buf[BUFSIZE];//存放copy的数据最大1024个字节 int pos,len,ret;//位置,长度,返回值 if(argc < 3) { fprintf(stderr,"Usage...\n"); exit(1); } do { sfd = open(argv[1],O_RDONLY); if(sfd < 0) { if(errno != EINTR)//如果是假错(信号会打断阻塞的系统调用错误为EINTR) { perror("open()"); exit(1); } } }while(sfd < 0); do { dfd = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0600); if(dfd < 0) { if(errno != EINTR)//如果是假错(信号会打断阻塞的系统调用错误为EINTR) { close(sfd); perror("open()"); exit(1); } } }while(dfd < 0); while(1) { len = read(sfd,buf,BUFSIZE); if(len < 0) { if(errno == EINTR) continue; perror("read()"); break; } if(len == 0) break; // len > 0 pos = 0; while(len > 0) { ret = write(dfd,buf+pos,len); if(ret < 0) { if(errno == EINTR) continue; perror("write()"); exit(1); } pos += ret; len -= ret; } } close(dfd); close(sfd); exit(0); }
标准信号肯定会丢失,实时信号不会丢失哈哈
信号的不可靠:在程序三:signal函数只是规定了SIG_INT信号来 signal只是定义了执行行为,内核负责调用以及布置执行现场,但是如果信号在处理行为的同时来了一个相同的信号,那么这两次的执行现场可能不是在同一个位置,第一次的行为会被第二次的行为冲刷掉,说起来挺可悲的!
标签:
原文地址:http://www.cnblogs.com/muzihuan/p/4657876.html