- 信号的基本介绍
每个信号都有一个名字。这些名字都以三个字符 S I G开头。
很多条件可以产生一个信号
当用户按某些终端键时,产生信号。
硬件异常产生信号:除数为0、无效的存储访问等等。 - kill -l 看系统的信号
- 响应信号
默认、
忽略、SIGKILL SIGSTOP不能忽略
捕获并处理 SIGKILL SIGSTOP不能捕获并处理
信号处理函数
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
SIGINT
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handler(int s){
printf("你弄不死我\n");
}
int main( void) {
signal(SIGINT, handler);
for ( ; ; ) {
printf(".");
fflush(stdout);
sleep(1);
}
}
------------------------------------------------
[root@localhost ~]# ./a.out
.....^C你弄不死我
....^C你弄不死我
.....^\退出(吐核)
信号的分类
- 可靠信号
- 不可靠信号
- 非实时信号
- 实时信号SIGRH
kill
int kill(pid_t pid, int signo) ;
kill的p i d参数不同的情况:
- pid > 0 将信号发送给进程ID为pid的进程。
- pid == 0 将信号发送给其进程组ID等于发送进程的进程组ID,而且发送进程有许可权向其发送信号的所有进程。
- pid < 0 将信号发送给其进程组ID等于pid绝对值,而且发送进程有许可权向其发送信号
的所有进程。如上所述一样,“所有进程”并不包括系统进程集中的进程。
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handler(int s) {
printf("recv %d\n", s);
exit(0);
}
int main( void ) {
signal(SIGUSR1, handler);
pid_t pid = fork();
if ( pid == 0 ) {
sleep(3);
kill(getppid(), SIGUSR1);
} else {
for ( ; ; ) {
printf(".");
fflush(stdout);
}
}
}
打印彩色9*9乘法表
#include <stdio.h>
#include <stdlib.h>
int main( void ) {
int i, j;
for (i=1; i<=9; i++) {
for (j=1; j<=i; j++) {
printf("\033[3%dm%dX%d=%-3d ", (i%8), j, i, i*j);
}
printf("\n");
}
printf("\033[0m");
}
信号在内核中的表示
信号从产生到执行信号处理函数,把执行信号处理函数的动作称为抵达。
从产生到抵达之间的状态称为信号未决。
sigset_t
:信号集
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
SIG_BLOCK mask |= *set
SIG_UNBLOCK mask &= ~set
SIG_SETMASK mask *= *set
模拟弹出U盘
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handler(int s) {
printf("recv %d\n", s);
}
int main( void ) {
signal(SIGINT, handler);
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigprocmask(SIG_BLOCK, &set, NULL);
int i;
for (i=0; i<5; i++) {
printf("开始拷贝%d集视频\n", i+1);
sleep(3);
printf("第%d集视频拷贝完毕\n", i+1);
}
// 解除信号屏蔽
sigprocmask(SIG_UNBLOCK, &set, NULL);
for ( ; ; ) {
printf(".");
sleep(1);
fflush(stdout);
}
}
-------------------------------------------
/*[root@localhost ~]# ./a.out
开始拷贝1集视频
^C第1集视频拷贝完毕
开始拷贝2集视频
^C^C^C^C^C^C^C第2集视频拷贝完毕
开始拷贝3集视频
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C第3集视频拷贝完毕
开始拷贝4集视频
^C^C^C^C第4集视频拷贝完毕
开始拷贝5集视频
第5集视频拷贝完毕
recv 2
..^C.recv 2
..^C.recv 2
..^\退出(吐核)
*/
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handler(int s) {
printf("recv %d\n", s);
}
int main(void) {
struct sigaction act;
act.sa_handler = handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGINT, &act, NULL);
for ( ; ; ) {
printf(".");
fflush(stdout);
sleep(1);
}
}
----------------------------------------------
/*[root@localhost ~]# ./a.out
.......^Crecv 2
....^Crecv 2
..^\退出(吐核)
*/
IPC进程间通信:互斥、同步
进程间通信的目的:数据传递、资源共享、通知事件
进程间通信方式:管道、syatem V 进程间通信 IPC、消息队列、共享内存、信号量
POSIX 进程间通信:信号量、信号、互斥量、读写锁、自旋锁、条件变量
死锁的必要条件:互斥性、请求并保持、不可剥夺、环路等待
银行家算法:
1.客户的最大资金需求,不超过银行家现有的资金,接纳该客户。
2.客户可以分期贷款,但是贷款的总额不能超过最大资金需求量。
3.当银行家现有的资金量不能满足客户需求,总能在有限的时间内贷款给客户。
4.客户拿到全部资金后,总能够在有限的时间内归还。