第六章信号与信号处理

第六章信号与信号处理

  • 6.1信号和中断
    由I/O设备或者协议处理器发送到外部请求,它将CPU从正常执行转移到中断处理。
    (1)人员中断,人员再次上线后能够继续之前的事项
    (2)进程中断,来源如下
    1.硬件中断
    2.来自其他进程
    3.自己造成(除以0,无效地址)
    (3)硬件中断,情况如下
    1.来自硬件
    2.来自其他处理器的中断
    3.自己造成
    (4)进程的陷阱错误
  • 6.2Unix/Linux信号示例
    (1)Ctrl+C 终止当前进程。键盘中断处理程序将Ctrl+C转换成SIGINT(2)信号,发送给终端上的进程。在内核模式下,每个进程都要检查和处理未完成的信号,进程对绝大多数信号是调用系统内核的kexit(exitValue)函数来终止。Linux中exitValue的低位字节是导致进程终止的信号。
    (2)Nohup a.out &命令在后台运行一个程序。及时用户退出程序依然执行。忽略SIGINT(1)信号。当用户退出时sh会向子程序发送SIGHUP信号,子程序忽略之。
    (3)Kill pid (or kill -s 9 pid)杀死进程,执行杀死的进程向pid标识的目标发送SIGTERM(15)信号,请求它死亡。如果拒绝使用括号中的强制执行。
  • 6.3 Unix/Linux中的信号处理
    (1)型号类型(signal.h)

(2)信号来源
·硬件中断
1.中断键SIGINT(2)
2.间隔定时器SIGALRM(14)、SIGVTALRM(26)、SIGPROF(27)
3.总线错误、IO陷阱

·异常
如通常陷阱信号SIGEPE(8)表示除以0,SIGSEGV(11)段错误

·其他进程
进程使用kill(pid,sig)。杀死无限循环进程。


(3)进程PROC结构体中的信号
每个进程PROC都有一个32位的向量,用来记录发送给程序的信号。位向量中每一位表示信号编号(0位除外),一个信号MASK位向量,用来屏蔽相应信号,使用sigmask、sigsetmask、siggetmask、sigblock等来设置、清除、检查MASK信号。
(4)信号处理函数
信号处理数组int sig[32]。数组每个条目都指定了如何处理相应的信号,0表示默认,1表示忽略,其他非0值表示用户模式下预先安装的信号捕捉函数。

(5)安装信号捕捉函数
进程系统调用

修改选定信号编号的处理函数,SIGKILL(9)和SIGSTOP(19)除外。已安装的处理函数一定是以下形式用户空间中信号捕捉函数的入口:

1.执行已安装的信号捕捉函数之前,通常将信号设置为默认。为捕捉下次出现的相同信号,必须重新安装捕捉系统。

实例

点击查看代码
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<string.h>
void handler(int sig,siginfo_t *siginfo,void *context)
{
	printf("handler:sif=%d from PID=%d UID=%d\n",sig,siginfo->si_pid,siginfo->si_uid);
}

int main(int argc,char *argv[])
{
	struct sigaction act;
	memset(&act,0,sizeof(act));
	act.sa_sigaction = &handler;//添加响应函数
	act.sa_flags = SA_SIGINFO;
	sigaction(SIGTERM,&act,NULL);//将行为act放入响应处理机制
	printf("proc PID=%d looping\n",getpid());
	printf("enter kill PID to send SIGTERM signal to it\n");
	while(1)//一直循环
	{
		sleep(10);
	}
}
**运行结果** ![](https://img2022.cnblogs.com/blog/2171853/202210/2171853-20221029230521794-630420539.png)

·函数调用和命令

  • 6.4信号处理步骤
    (1)当某进程处于内核模式是,会检查并处理未完成的信号。
    (2)重置用户安装的信号捕捉器。
    (3)信号和唤醒。

  • 6.5信号与异常
    Unix设计最初用途如下

  • 6.7信号做为IPC

  • 6.7 Linux中的IPC
    进程之间通信的机制。

  • 6.7.1管道和FIFO

  • 6.7.2信号

  • 6.7.3System V IPC
    在POSIX标准下,包括共享内存、信号量和消息队列。

  • 6.7.4 POSIX消息队列
    类似于System V IPC的消息队列,更通用且具有移植性

  • 6.7.5线程同步机制
    Linux不区分进程和线程。在Linux中,进程共享某些公共资源的线程。如果是使用共享地址空间的clone()系统调用创建的线程,他们通过共享内存进行通信。

  • 6.7.6 套接字
    跨网络通信的的IPC机制。

  • 6.8编程项目

点击查看代码
#include<stdio.h>
#include<signal.h>
#include<fcntl.h>
#include<string.h>

#define LEN 64
int ppipe[2];
int pid;
char line[LEN];
int parent()
{
	printf("parent %d running \n",getpid());
	close(ppipe[0]);
	while(1)
	{
	printf("parent %d:input a line :\n",getpid());
	fgets(line,LEN,stdin);
	line[strlen(line)-1] = 0; // kill the \n at and
	printf("parent %d write to pipe\n",getpid());
	write(ppipe[1],line,LEN);
	printf("printf %d send signal 10 to %d\n",getpid(),pid);
	kill(pid,SIGUSR1);
	}
}

void chandler(int sig)
{
printf("\nchild %d got an interrupt sig=%d\n",getpid(),sig);
read(ppipe[0],line,LEN);
printf("child %d get a message =%s\n",getpid(),line);
}
int child()
{
	char msg[LEN];
	int parent = getppid();
	printf("child %d running \n",getpid());
	close(ppipe[1]);
	signal(SIGUSR1,chandler);
	while(1);
}

int main()
{
	pipe(ppipe);
	pid = fork();
	if(pid) parent();
	else child();
}
**运行结果**




posted @ 2022-10-29 23:07  岳华  阅读(44)  评论(0编辑  收藏  举报