进程间通信--信号(进程间通信唯一的异步方式)
来源:互联网 发布:音乐变调器软件 编辑:程序博客网 时间:2024/05/18 18:21
一、信号的介绍
信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式。
信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了那些系统事件。
如果该进程当前并未处于执行态,则该信号就由内核保存起来,直到该进程恢复执行再传递个它;如果一个信号被进程设置为阻塞,则该信号的传递被延迟,直到其阻塞取消时才被传递给进程。
二、linux操作系统支持的信号
A. kill -l
B.常用信号的含义
B.常用信号的含义
三、信号的产生
A.用户在终端按下某些键时,终端驱动程序会发送信号给前台进程,例如ctr+c产生SIGINT, ctr + \产生SIGQUI信号,ctr + z产生SIGTSTP。
B.硬件异常产生信号,这些条件由硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释为SIGFPE信号发送给进程。再比如当前进程访问了非法内存地址,MMU会产生异常,内核将这个异常解释为SIGSEGV信号发送给当前进程 。
C.一个进程调用int kill(pid_t pid,int sig)函数可以给另一个进程发送信号
D.可以用kill命令给某个进程发送信号,如果不明确指定信号则发送SIGTERM信号,该信号的默认处理动作是终止进程。
E.当内核检测到某种软件条件发生时也可以通过信号通知进程,例如闹钟超时产生SIGALRM信号,向读端已关闭的管道写数据时产生SIGPIPE信号。
四、进程对信号的处理
A.忽略此信号
B.执行该信号的默认处理动作
C.提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数,这种方式成为捕捉(Catch)一个信号。
五、相关信号API
A.通过系统调用向一个指定的进程发送信号
运行结果如下:
B.捕捉一个信号
对应的API
其原型:
参数说明:
第一个参数:指定发送信号的接收线程
第二个参数:信号的signum
案例一、
父进程从终端输入signum,然后发给子进程
点击(此处)折叠或打开
- #include <stdio.h>
- #include <sys/types.h>
- #include <signal.h>
- #include <stdlib.h>
- int main()
- {
- int pid;
- if((pid = fork()) < 0)
- {
-
- perror("Fail to fork");
- exit(EXIT_FAILURE);
-
- }else if(pid == 0){
-
- while(1);
-
- }else{
-
- int signum;
-
- while(scanf("%d",&signum) == 1)
- {
- kill(pid,signum);
- system("ps -aux | grep a.out");
- }
- }
- return 0;
- }
运行结果如下:
B.捕捉一个信号
对应的API
其原型:
我们一般都是用第一个,也就是通过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);
- }
C.闹钟函数alarm
larm()也称为闹钟函数,它可以在进程中设置一个定时器。当定时器指定的时间到时,内核就向进程发送SIGALARM信号。
seconds:指定的秒数,如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。
成功:如果调用此alarm()前,进程中已经设置了闹钟时间,则放回上一个闹钟时间的剩余时间,否则返回0。
alarm(100);
........
......
alarm(5);
出错:-1
案例探究:
运行结果如下:
点击(此处)折叠或打开
- #include <stdio.h>
- #include <signal.h>
- #include <stdlib.h>
- void handler(int signum)
- {
- if(signum == SIGALRM)
- {
- printf("Recv SIGALARM.\n");
- }
- exit(EXIT_SUCCESS);
- }
- int main()
- {
- int count = 0;
- int n = 0;
- signal(SIGALRM,handler);
- n = alarm(10);
- printf("n = %d.\n",n);
-
- sleep(2);
- n = alarm(5);
- printf("n = %d.\n",n);
-
- while(1)
- {
- printf("count = %d.\n", ++count);
- sleep(1);
- }
- return 0;
- }
案例二、综合案例
使用FIFO实现clientA与clientB之间聊天
A.输入quit后,两个进程退出
B.如果在20秒内,没有等到另一端发来的消息,则认为对方已不在,此时终止。
clientA:
client B
D.将进程挂起函数pause
案例如下:
点击(此处)折叠或打开
- #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[n] = '\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[n] = '\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);
- }
D.将进程挂起函数pause
解释如下:
案例如下:
0
上一篇:进程间通信---共享内存
下一篇:linux 进程(二) --- 进程的创建及相关api
相关热门文章
- linux 常见服务端口
- xmanager 2.0 for linux配置
- 【ROOTFS搭建】busybox的httpd...
- openwrt中luci学习笔记
- 什么是shell
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
0 0
- 进程间通信--信号(进程间通信唯一的异步方式)
- 进程间通信--信号(进程间通信唯一的异步方式)
- 进程间通信--信号(进程间通信唯一的异步方式)
- 进程间通信--信号(进程间通信唯一的异步方式)
- 进程间通信--信号(进程间通信唯一的异步方式)
- 进程间通信--信号(进程间通信唯一的异步方式)
- Linux进程间的通信方式:信号
- 信号--进程间的通信
- 进程间的信号通信
- 进程间的 信号 通信
- 进程间的信号通信
- 进程间的信号通信
- 信号通信(进程间通信)
- 进程间的通信之信号通信
- 进程间通信-信号
- 进程间通信--信号
- 进程间通信--信号
- 进程间通信-信号
- Linux内核很吊之 module_init解析 (下)
- Linux网络编程:原始套接字的魔力【上】
- 进程间通信---共享内存
- E: 软件包 atom 需要重新安装,但是我无法找到相应的安装文件。
- Ubuntu安装磁共振处理软件Fsl步骤
- 进程间通信--信号(进程间通信唯一的异步方式)
- linux 进程(二) --- 进程的创建及相关api
- linux 标准IO缓冲机制探究
- 进程间同步---system v ipc 对象信号灯集
- Linux 原始套接字--myping的实现
- u-boot启动完全分析
- ssh框架整合实例
- linux网络编程——套接字(socket)入门
- samba移植到android流程
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
藕带是什么
泡椒藕带
藕带怎么炒
炒藕带
藕带种植
藕带怎么吃
泡藕带
蜜汁藕
蜜汁糖藕
藕汁的功效与作用
藕汁的做法
蜜汁藕的做法
藕烈18r
藕烈r18
炸藕盒
煎藕盒
藕盒的做法
红烧藕盒
炸藕盒面糊怎么调窍门
藕盒的家常做法窍门
炸藕盒的家常做法
正宗炸藕盒的糊怎么调
藕盒的家常做法
蒸藕盒
炸藕盒的做法
怎么炸藕盒又软又酥的做法
藕粉功效
藕粉怎么吃
孕妇吃藕粉
藕粉减肥
藕粉热量
西湖藕粉
藕粉吃法
藕粉的吃法
藕粉怎么做
藕粉的功效
自制藕粉
藕粉丸子
怎么泡藕粉
泡藕粉
三家村藕粉