回顾:
1.信号的作用
2.理解信号:
软中断
可靠与不可靠 kill-l
3.信号发送与注册kill/raise alarm setitimer signal
4.信号的屏蔽sigprocmask sigemptyset sigfillset
5.信号屏蔽切换
sigpending
sigsuspend
=pause + 指定屏蔽的信号
pause与sigsuspend都会被信号中断
中断的是pause与sigsuspend,不是进程中其他代码
sigsuspend放在sigprocmask环境中思考:
5.1sigsuspend是否影响sigprocmask屏蔽的信号呢?
影响,使原来屏蔽信号全部失效
当sigsuspend返回,恢复原来的屏蔽信号
5.2sigsuspend什么时候使用?
一、最新版本的发送与处理
sigqueue/sigaction
1.思考:
信号中断函数调用中是否被其他信号中断。
信号函数调用中只屏蔽本身信号,不屏蔽其他信号
2.怎么保证函数调用中屏蔽指定的信号呢?
sigaction可以指定处理函数调用的屏蔽信号
sigaction在处理信号的时候,接收数据。
sigqueue发送信号的时候,可以发送数据
sigaction/sigqueue是signal/kill的增强版本
3.函数说明
使用sigaction/sigqueue有两个理由。
3.1稳定
3.2增强功能
intsigaction(
intsig, //被处理信号
conststruct sigaction *action, //处理函数及其参数
structsigaction *oldact //返回原来的处理函数结构体
)
返回值:
0:成功
-1:失败
structsigaction
{
void(*sa_handle)(int);
void(*sa_sigaction)(int, siginfo_t*, void*);
sigset_t*mask; //屏蔽信号
intflags; //SA_SIGINFO
void** //保留成员
}
案例:
1.使用sigaction处理信号,使用kill发送信号
2.使用sigaction处理信号,使用sigqueue发送信号
3.发送信号的同时处理数据。
二、IPC
1.基于文件
1.1无序文件
1.2有序文件
1.1.1管道
1.1.1.1有名
1.1.1.2匿名
1.1.2socket
2.基于内存
2.1无序内存
2.1.1匿名内存
2.1.2共享内存
2.2有序内存
2.2.1共享队列
3.同步:基于内存IPC应用(共享内存数组)
信号量/信号灯
三、基于普通文件的IPC
IPC的技术提出的应用背景
进程之间需要同步处理:
同步需要通信
普通文件就是最基本的通信手段。
普通文件IPC技术问题:
一个进程改变文件,另外一个进程无法感知
解决方案:
一个特殊的文件:管道文件
四、管道文件
1.创建管道文件mkfifo()
2.体会管道文件特点
案例:
fifoA fifoB
建立管道
打开管道 打开管道
写数据 度数据
关闭管道 关闭管道
删除管道
建立管道文件方法:
使用Linux的指令mkfifo
总结:
1.read没有数据read阻塞,而且read后数据是被删除
2.数据有序
3.打开的描述符号可以读写(two-way双工)
4.管道文件关闭后,数据不持久。
5.管道的数据存储在内核缓冲中。
五、匿名管道
发现有名的管道的名字紧紧是内核识别是否返回同一个fd(文件描述符)的标识
所以当管道名失去表示作用的时候,实际可以不要
在父子进程之间:打开文件描述符后创建进程。
父子进程都有描述符。管道名没有价值。
所以在父子进程中引入一个没有名字的管道:匿名管道
结论:
匿名管道只能使用在父子进程。
1.创建匿名管道
2.使用匿名管道
案例:
匿名管道的创建
体会匿名管道的特点
intpipe(int fd[2]); //创建一个管道打开管道拷贝管道关闭读写
fd[0]:只读(不能写)
fd[1]:只写(不能读)
注意:数据无边界。
综合:
建立两个子进程:
一个负责计算1-5000的素数
另外一个负责计算5001-10000的素数
父进程负责存储
Sigmask.c |
#include<stdio.h> #include<stdlib.h> #include<signal.h> #include<unistd.h>
main() { int sum = 0; int i; for(i = 0; i < 10; i ++) { sum += i; sleep(1); //模拟业务处理时间比较长 } printf("%d\n", sum); printf("over\n"): } |
makefile |
sigmask: gcc sigmask.c -o sigmask |
#include<stdio.h> #include<stdlib.h> #include<signal.h> #include<unistd.h>
void handle(int s) { printf("signal disturb!!\n"); }
main() { int sum = 0; int i; signal(SIGINT, handle); for(i = 0; i < 10; i ++) { sum += i; sleep(1); //模拟业务处理时间比较长 } printf("%d\n", sum); printf("over\n"): } |
上面for循环中,随时可能中断。 |
#include<stdio.h> #include<stdlib.h> #include<signal.h> #include<unistd.h>
void handle(int s) { printf("signal disturb!!\n"); }
main() { int sum = 0; int i;
sigset_t sigs; //屏蔽步骤1 定义信号集 sigemptyset(&sigs); //屏蔽步骤2 清空信号集 sigaddset(&sigs, SIGINT); //屏蔽步骤3 添加被屏蔽的信号
signal(SIGINT, handle); sigprocmask(SIG_BLOCK, &sigs, 0);//屏蔽步骤4 添加被屏蔽的代码块开始 for(i = 0; i < 10; i ++) { sum += i; sleep(1); //模拟业务处理时间比较长 } printf("%d\n", sum); sigprocmask(SIG_UNBLOCK, &sigs, 0);//屏蔽步骤4 添加被屏蔽的代码块结束 printf("over\n"): } |
在程序执行过程中多次的信号被压缩为一次 |
Suspend.c |
#include<stdio.h> #include<stdlib.h> #include<signal.h> #include<unistd.h>
void handle(int s) { printf("signal disturb!!\n"); }
main() { sigset_t sigs; sigemptyset(&sigs);
signal(SIGUSR1, handle);
sigsuspend(&sigs); //挂起 printf("over\n"): } |
#include<stdio.h> #include<stdlib.h> #include<signal.h> #include<unistd.h>
main() { sigset_t sigs; sigemptyset(&sigs);
sigsuspend(&sigs); //挂起 printf("over\n"): } |
#include<stdio.h> #include<stdlib.h> #include<signal.h> #include<unistd.h>
main() { pause(); printf("over\n"): } |
#include<stdio.h> #include<stdlib.h> #include<signal.h> #include<unistd.h>
void handle(int s) { printf("signal disturb!!\n"); }
main() { sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs, 2); sigaddset(&sigs, 10); signal(SIGUSR2, handle);
sigsuspend(&sigs); //挂起 printf("over\n"): } |
#include<stdio.h> #include<stdlib.h> #include<signal.h> #include<unistd.h>
void handle(int s) { printf("signal disturb!!\n"); }
main() { int sum = 0; int i;
sigset_t sigs, sigt; sigemptyset(&sigs); sigemptyset(&sigt); sigaddset(&sigs, SIGINT);
signal(SIGINT, handle); sigprocmask(SIG_BLOCK, &sigs, 0); for(i = 0; i < 10; i ++) { sum += i; sleep(1); sigsuspend(&sigt); } printf("%d\n", sum); sigprocmask(SIG_UNBLOCK, &sigs, 0); printf("over\n"): } |
Demo41.c |
#include<stdio.h> #include<stdlib.h> #include<signal.h> #include<unistd.h>
void handle(int s) { printf("out copy over !\n"); }
main() { int sum = 0; int i;
sigset_t sigs, sigt; sigemptyset(&sigs); sigemptyset(&sigt); sigaddset(&sigs, SIGINT);
signal(SIGINT, handle);
for(i = 0; i < 10; i ++) //可能中断,导致刚要指向就中断 { sigprocmask(SIG_BLOCK, &sigs, 0); //存在漏洞 sum += i; printf("copy start\n"); sleep(5); sigprocmask(SIG_UNBLOCK, &sigs, 0); printf("copy over\n") sigsuspend(&sigt); } printf("%d\n", sum);
printf("over\n"): } |
#include<stdio.h> #include<stdlib.h> #include<signal.h> #include<unistd.h>
void handle(int s) { printf("out disturb start!\n"); sleep(3); printf("out disturb end!\n"); }
main() { int i;
sigset_t sigs, sigt,sigu; sigemptyset(&sigs); sigemptyset(&sigt); sigemptyset(&sigu); sigaddset(&sigs, SIGINT);
signal(SIGINT, handle); sigprocmask(SIG_BLOCK, &sigs, 0) for(i = 0; i < 10; i ++) { printf("copy start %d\n", i); sleep(5); printf("copy end %d\n", i) sigpending(&sigu); if(sigismember(&sigu, SIGINT)) { sigsuspend(&sigt); }
} printf("all copy over", sum); sigprocmask(SIG_UNBLOCK, &sigs, 0) printf("over\n"): } |