UNIX环境高级编程之-----信号signal
2015-06-19 00:45
274 查看
参考书籍:unxi环境高级编程
信号函数:
其原型为:
我们一般都是用第一个,也就是通过typedef改写过的。
注意:signal函数我一般认为其是向内核注册当前进程收到信号的处理的方式。
signal(SIGINT,handler);
参数说明:
signum : 指定信号
handler : SIG_IGN忽略该信号,SIG_DFL采用系统默认方式处理信号,自定义的信号处理函数指针。
理解实际的例子是学习的最好方式:
例子一:
通过异步方式,给子进程收尸
注意:子进程在终止时会给父进程发SIGCHLD,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需要专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。
运行结果如下:
[uglychen@chenxun test]$gcc test.c
[uglychen@chenxun test]$ ls
a.out test.c
[uglychen@chenxun test]$ ./a.out
child loop.
Father loop.
child loop.
Father loop.
child loop.
child loop.
Father loop.
child loop.
Child exit.
Father loop.
Father loop.
[uglychen@chenxun test]$
例二、综合案例
使用FIFO实现clientA与clientB之间聊天
A.输入quit后,两个进程退出
B.如果在20秒内,没有等到另一端发来的消息,则认为对方已不在,此时终止。
client B
信号函数:
typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);
其原型为:
void (*signal(int signum,void (*handler)(int))) (int);
我们一般都是用第一个,也就是通过typedef改写过的。
注意:signal函数我一般认为其是向内核注册当前进程收到信号的处理的方式。
signal(SIGINT,handler);
参数说明:
signum : 指定信号
handler : SIG_IGN忽略该信号,SIG_DFL采用系统默认方式处理信号,自定义的信号处理函数指针。
理解实际的例子是学习的最好方式:
例子一:
通过异步方式,给子进程收尸
注意:子进程在终止时会给父进程发SIGCHLD,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需要专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。
#include <stdio.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> void child_exit_handler(int signum) { if(signum == SIGCHLD) { printf("Child exit.\n"); wait(NULL); } } int main() { int pid; int i = 0; //想内核注册,处理 SIGCHLD信号的方式 signal(SIGCHLD,child_exit_handler); if((pid = fork()) < 0) { perror("Fail to fork"); exit(EXIT_FAILURE); }else if(pid == 0){ for(i = 0;i < 5;i ++) { printf("child loop.\n"); sleep(1); } }else{ for(i = 0;i < 5;i ++) { printf("Father loop.\n"); sleep(2); } } exit(EXIT_SUCCESS); }
运行结果如下:
[uglychen@chenxun test]$gcc test.c
[uglychen@chenxun test]$ ls
a.out test.c
[uglychen@chenxun test]$ ./a.out
child loop.
Father loop.
child loop.
Father loop.
child loop.
child loop.
Father loop.
child loop.
Child exit.
Father loop.
Father loop.
[uglychen@chenxun test]$
例二、综合案例
使用FIFO实现clientA与clientB之间聊天
A.输入quit后,两个进程退出
B.如果在20秒内,没有等到另一端发来的消息,则认为对方已不在,此时终止。
clientA:
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <string.h> #include <fcntl.h> #define MAX 100 void signal_handler(int signum) { static int flag = 0; switch(signum) { case SIGALRM: if(flag == 0) { printf("The people is leaving,the system is closed in 10 seconds \ and you can input 'ctrl + c' cancel.\n"); alarm(10); }else{ kill(getppid(),SIGKILL); usleep(500); exit(EXIT_SUCCESS); } flag = 1; break; case SIGINT: printf("The alarm is cancel.\n"); alarm(0); break; } } int child_recv_fifo(char *fifo_name) { int n,fd; char buf[MAX]; if((fd = open(fifo_name,O_RDONLY)) < 0) { fprintf(stderr,"fail to open %s : %s.\n",fifo_name,strerror(errno)); return -1; } signal(SIGALRM,signal_handler); signal(SIGINT,signal_handler); alarm(15);//璁剧疆瀹氭椂鍣? while(1) { n = read(fd,buf,sizeof(buf)); buf = '\0'; printf("Read %d bytes : %s.\n",n,buf); if(strncmp(buf,"quit",4) == 0 || n == 0) { kill(getppid(),SIGKILL); usleep(500); exit(EXIT_SUCCESS); } alarm(15); } return 0; } int father_send_fifo(char *fifo_name,int pid) { int n,fd; char buf[MAX]; if((fd = open(fifo_name,O_WRONLY)) < 0) { fprintf(stderr,"Fail to open %s : %s.\n",fifo_name,strerror(errno)); return -1; } signal(SIGINT,SIG_IGN); while(1) { getchar(); printf(">"); fgets(buf,sizeof(buf),stdin); buf[strlen(buf)-1] = '\0'; write(fd,buf,strlen(buf)); if(strncmp(buf,"quit",4) == 0) { kill(pid,SIGKILL); usleep(500); exit(EXIT_SUCCESS); } } return 0; } int main(int argc,char *argv[]) { int pid; if(argc < 3) { fprintf(stderr,"usage %s argv[1].\n",argv[0]); exit(EXIT_FAILURE); } if(mkfifo(argv[1],0666) < 0 && errno != EEXIST) { perror("Fail to mkfifo"); exit(EXIT_FAILURE); } if(mkfifo(argv[2],0666) < 0 && errno != EEXIST) { perror("Fail to mkfifo"); exit(EXIT_FAILURE); } if((pid = fork()) < 0) { perror("Fail to fork"); exit(EXIT_FAILURE); }else if(pid == 0){ child_recv_fifo(argv[2]); }else{ father_send_fifo(argv[1],pid); } exit(EXIT_SUCCESS); }
client B
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <string.h> #include <fcntl.h> #define MAX 100 void signal_handler(int signum) { static int flag = 0; switch(signum) { case SIGALRM: if(flag == 0) { printf("The people is leaving,the system is closed in 10 seconds \ and you can input 'ctrl + c' cancel.\n"); alarm(10); }else{ kill(getppid(),SIGKILL); usleep(500); exit(EXIT_SUCCESS); } flag = 1; break; case SIGINT: printf("The alarm is cancel.\n"); alarm(0); break; } } int child_recv_fifo(char *fifo_name) { int n,fd; char buf[MAX]; if((fd = open(fifo_name,O_RDONLY)) < 0) { fprintf(stderr,"fail to open %s : %s.\n",fifo_name,strerror(errno)); return -1; } signal(SIGALRM,signal_handler); signal(SIGINT,signal_handler); alarm(15);//璁剧疆瀹氭椂鍣? while(1) { n = read(fd,buf,sizeof(buf)); buf = '\0'; printf("Read %d bytes : %s.\n",n,buf); if(strncmp(buf,"quit",4) == 0 || n == 0) { kill(getppid(),SIGKILL); usleep(500); exit(EXIT_SUCCESS); } alarm(15); } return 0; } int father_send_fifo(char *fifo_name,int pid) { int n,fd; char buf[MAX]; if((fd = open(fifo_name,O_WRONLY)) < 0) { fprintf(stderr,"Fail to open %s : %s.\n",fifo_name,strerror(errno)); return -1; } signal(SIGINT,SIG_IGN); while(1) { getchar(); printf(">"); fgets(buf,sizeof(buf),stdin); buf[strlen(buf)-1] = '\0'; write(fd,buf,strlen(buf)); if(strncmp(buf,"quit",4) == 0) { kill(pid,SIGKILL); usleep(500); exit(EXIT_SUCCESS); } } return 0; } int main(int argc,char *argv[]) { int pid; if(argc < 3) { fprintf(stderr,"usage %s argv[1].\n",argv[0]); exit(EXIT_FAILURE); } if(mkfifo(argv[1],0666) < 0 && errno != EEXIST) { perror("Fail to mkfifo"); exit(EXIT_FAILURE); } if(mkfifo(argv[2],0666) < 0 && errno != EEXIST) { perror("Fail to mkfifo"); exit(EXIT_FAILURE); } if((pid = fork()) < 0) { perror("Fail to fork"); exit(EXIT_FAILURE); }else if(pid == 0){ child_recv_fifo(argv[1]); }else{ father_send_fifo(argv[2],pid); } exit(EXIT_SUCCESS); }
相关文章推荐
- Ruby On Rails -- 开发流程
- Spring IOC的配置使用
- java基础—集合 Vcetor 基本方法演示
- 10.Spring Bean的生命周期
- Ruby On Rails -- Rails的安装
- 已知有枚举类型定义:enum MyEn{a=101,b,c=207,d,e,f,g},编程输出第5个枚举元素的序号值
- C#中的一些访问修饰符
- Java基本数据类型知识总结
- Spring IOC容器基本原理
- [Deep Learning]任意层cnn的matlab版本实现
- 【编程经验】一个关于常量不能被修改的错误
- java正则表达式速记
- Java-马士兵设计模式学习笔记-工厂模式-用Jdom模拟Spring
- Yii2 数据库操作汇总
- scrapy爬豆瓣电影
- Ubuntu下 vi编写第一个C语言程序
- 详解Python中的日志模块logging
- Python写的一个简单监控系统
- php结合正则获取字符串中数字
- php实现通过ftp上传文件