1.信号是什么:
信号在软件层对硬件层中断的一种模拟,是一个异步信号
具体来说:信号是一种向进程发送通知,告诉其某件事情发生了的一种简单通信机制
中断:是一种优先级高的代码事件
2.linux所提供的信号:
2.1查看所有信号:kill -l
2.2发送信号给进程:kill + -信号码 + 进程PID
3.信号的原理:
进程的进程表(task_struct)中会有一个“信号处理方式登记表”,专门用于记录信号的处理方式,调用signal函数设置某个信号的理方式时,会将信号的处理方式登记到该表中,每个进程拥有独立的task_struct结构体变量,因而每个进程的“信号处理方式登记表”都是独立的,所以每个进程对信号的处理方式自然也是独立的,互不干扰
函数原型:
sighandler_t signal(int signum, sighandler_t handler);
参数1:信号编号
参数2:信号处理方式
忽略:SIG_IGN
默认:SIG_DFL
捕获:填写类型为void (*)(int)的捕获函数的地址
头文件:
#include
typedef void (*sighandler_t)(int);
函数功能:
设置某个信号的处理方式,处理方式可以被设置为忽略,捕获,默认
SIGKILL和SIGSTOP是不能被捕捉的
返回值:
成功:返回上一次的处理方式
失败:返回SIG_ERR宏值,errno被设置
3.1信号发送API
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<signal.h>
int main()
{
printf("rebort 5s\n");
sleep(5);
1.kill(-1,SIGINT);给所有进程发送SIGINT信号
2.raise(SIGINT)给当前进程发送信号
3.alarm(5); 5s后终止,给当前进程发送SIGALRM信号
4.abort() 产生SIGABRT终止进程,调abort函数是产生
while(1);
return 0;
}
3.2信号的处理方式(3种)
1. 执行默认操作(默认) SIG_DFL
2. 执行用户需要执行的操作(捕获)指向自定义的函数指针,函数指针void(*)(int)
3.忽略:SIG_IGN
回调函数
1.SIG_IGN 忽略
2.SIG_DFL 默认执行
3.void(*hanshu)(int); 捕捉
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<signal.h>
void print()
{
printf("hekko\n");
while(1);
}
int main(int argc, char const *argv[])
{
signal(SIGALRM,SIG_IGN);//忽略
sleep(2);
signal(SIGALRM,SIG_DFL);//默认操作
signal(SIGALRM,print);
alarm(2);
printf("hello world\n");
pause();//用户处理了一个信号,唤醒
return 0;
}
3.3 IO常见的模型
1.阻塞:
- 当用户线程发起IO请求后,会进行系统调用(system call)来让内核(Kernel)进行IO操作
- 此时用户线程阻塞,等待内核将数据准备好
- 内核将数据准备好后会将数据从内核空间拷贝到用户空间,并返回给用户线程结束阻塞。
2.非阻塞:
- 由用户线程发起IO请求, 进行系统调用来让内核进行IO操作
- 此时如果内核没有准备好数据则会直接返回error,并不会阻塞用户线程,用户线程可以重复的发起IO请求
- 当用户线程发起请求并且内核已经将数据准备好后,会将数据从内核空间拷贝到用户空间(这个过程是需要阻塞用户线程的),返回给用户
3.IO多路复用
- 用户线程调用select后进行系统调用(内核会监视所有select负责的socket),此时用户线程被阻塞
- 当内核将数据准备好后就会返回,并通知用户线程进行读取操作,此时内核将数据拷贝到用户空间并返回
4.异步IO
- 用户线程进行aio_read,进行系统调用切换到内核
- 内核立即返回,并不会阻塞用户线程
- 内核准备好数据后会将数据从内核空间拷贝到用户空间并通知用户线程操作已完成
3.5 利用signal函数完成僵尸进程的回收
通过子进程的状态发生改变会产生一个SIGCHLD信号,对这个信号进行处理
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
#include<string.h>
char buf[1024];
void myfun(int signum)
{
pid_t pid =wait(NULL);
printf("回收成功,进程ID为%d\n",pid);
}
int main(int argc, char const *argv[])
{
//注册信号处理函数
if(signal(SIGCHLD,myfun)==SIG_ERR)
{
perror("signal");
return -1;
}
//创建一个线程
pid_t pid=fork();
if(pid<0)
{
perror("fork");
exit(1);
}
if(pid==0)//子进程
{
int fd=open("a.txt",O_RDWR|O_CREAT,0664);
while(1)
{
memset(buf,0,sizeof(buf));
//read(0,buf,sizeof(buf));
write(fd,buf,strlen(buf));
break; //子进程优先于父进程退出,产生僵尸进程
//sleep(2);
}
close(fd);
exit(0);
}
else if(pid>0)//父进程
{
int fd=open("a.txt",O_RDWR|O_CREAT,0664);
while(1)
{
memset(buf,0,sizeof(buf));
read(fd,buf,sizeof(buf));
printf("buf=%s\n",buf);
sleep(2);
}
}
return 0;
}