首页 > 其他分享 >第六章学习笔记

第六章学习笔记

时间:2022-10-30 18:57:56浏览次数:51  
标签:中断 pid 笔记 学习 进程 int 信号 第六章 define

摘要:

  • 本章讲述了信号和信号处理;介绍了信号和中断的统一处理,有助于从正确的角度看待信号;将信号视为进程中断,将进程从正常执行转移到信号处理;
  • 解释了信号的来源,包括来自硬件、异常和其他进程的信号;然后举例说明了信号在Unix/Linux中的常见用法;
  • 详细解释了Unix/Linux中的信号处理,包括信号类型、信号向量位、信号掩码位、进程PROC结构体中的信号处理程序以及信号处理步骤;
  • 用示例展示了如何安装信号捕捉器来处理程序异常,如用户模式下的段错误;还讨论了将信号用作进程间通信(IPC)机制的适用性。

一、知识点归纳

信号和中断

中断是从I/O设备或协处理器发送到CPU的外部请求,将CPU从正常执行转移到中断处理。信号是发送给进程的请求,将进程从正常执行转移到中断处理。
(1)人员中断
人员的每个动作函数都是通过本能或经验实现的,每个中断都分配由一个唯一的ID识别号和一个预先安装的动作函数,人在收到中断请求时“执行”动作函数。

  • 来自硬件的中断
  • 来自其他人的中断
  • 自己造成的中断
  • 不可屏蔽(NMI)
  • 可屏蔽

(2)进程中断
每个进程中断都被转换为一个唯一ID号,发送给进程。Unix/Linux中的进程中断成为信号,编号为1—31.进程也可屏蔽某些类型的信号以推迟处理,必要时可能修改信号动作函数。

  • 来自硬件的中断:终端、间隔定时器的“^C”组合键等。
  • 来自其他进程的中断:kill(pid,SIG#)、death_of_child等。
  • 自己造成的中断:除以0、无效地址等。

(3)硬件中断
每个中断都有唯一的中断向量号。CPU不会导致任何自己造成的中断(除非出错)。

  • 来自硬件的中断:定时器、I/O设备等。
  • 来自其他处理器的中断:FFP、DMA、多处理器系统中的其他CPU。
  • 自己造成的中断:除以0、保护错误、INT指令。

(4)进程的陷阱错误
进程可能会自己造成中断,是由被CPU识别为异常的错误引起的(除以0、无效地址、非法指令、越权……),它会陷入操作系统内核,将陷阱原因转换为信号编号发送给自己。

Unix/Linux信号示例

  • Ctrl+C组合键:转换为SIGINT(2)信号,发送给终端,终止当前运行的进程。进程对大多数信号的默认操作是调用内核的kexit(exitValue)函数来终止。
  • 用户可使用nohup a.out命令在后台运行程序,nohup会使sh复刻子进程来执行程序,但子进程会忽略SIGNUP(1)信号。
  • 通过ps -u LTD发现后台进程仍在运行,可使用kill pid (or kill -s 9 pid)杀死进程。执行杀死的进程向pid标识的目标进程发送一个SIGTERM(15)信号,请求它死亡。
    如果进程忽略该信号,可能拒绝死亡,可以使用kill -s 9 pid必能杀死。

Unix/Linux中的信号处理

1.信号类型

Unix/Linux支持31种不同的信号,每种信号在signal.h文件中都有定义,每种信号都有一个符号名。

#define      SIGHUP      1
#define      SIGINT      2
#define      SIGQUIT     3
#define      SIGILL      4
#define      SIGTRAP     5
#define      SIGABRT     6
#define      SIGIOT      6
#define      SIGBUS      7
#define      SIGFPE      8
#define      SIGKILL     9
#define      SIGUSR1     10
#define      SIGSEGV     11
#define      SIGUSR2     12
#define      SIGPIPE     13
#define      SIGALRM     14
#define      SIGTERM     15
#define      SIGSTKFLT   16
#define      SIGCHLD     17
#define      SIGCONT     18
#define      SIGSTOP     19
#define      SIGTSTP     20
#dpfine      STGTTTN     21
#define      SIGTTOU     22
#define      SIGURG      23
#define      SIGXCPU     24
#define      SIGXFSZ     25
#define      SIGVTALRM   26
#define      SIGPROF     27
#define      SIGWINCH    28
#define      SIGPOLL     29
#define      SIGPWR      30
#define      SIGSYS      31

 

2.信号来源

  • 来自硬件中断的信号
    中断健(Ctrl+C)产生一个SIGINT(2)信号
    间隔定时器:SIGALRM(14)、SIGVTALRM(26)或SIGPROF(27)
    其他硬件错误:总线错误、I/O陷阱等
  • 来自异常的信号
    SIGFPE(8):浮点异常(除以0)
    SIGSEGV(11):段错误
  • 来自其他进程的信号
    可使用kill(pid,sig)系统调用向pid标识的目标进程发送信号。

 

信号处理步骤

  • 处于内核模式会检查思念好并处理未完成的信号。
  • 重置用户安装的信号捕捉函数
  • 信号和唤醒

 

 

信号与异常

  • 进程遇到异常,会陷入内核模式。若在内核模式下发生异常,则打印一条PANIC错误信息并停止;若在用户模式下发生异常,则终止并以内存转储进行调试。
  • 让进程通过预先安装的信号捕捉函数处理用户模式下的程序错误。
  • 特殊情况下,会让某个进程通过信号杀死另一个进程。

Linux中的IPC

  • 管道和FIFO
  • 信号
  • System V IPC
  • POSIX消息队列
  • 线程同步机制
  • 套接字

 

 

二、实践

段错误捕捉函数

#include<stdio.h>
#include<stdlib.h> 
#include<unistd.h> 
#include<signal.h> 
#include<setjmp.h>
#include<string.h>
jmp_buf env;
int count = 0;
void handler(int sig, siginfo_t *siginfo, void *context)
{
printf ("handler: sig=%d from PID=%d UID=%d count=%d\n",
               sig, siginfo->si_pid, siginfo->si_uid, ++count); 
    if (count >= 4) // let it occur up to 4 times
        longjmp(env, 1234);
}
int BAD()
{
int *ip = 0;
printf("in BAD(): try to dereference NULL pointer\n");
*ip = 123;    // dereference a NULL pointer
printf("should not see this line\n");
}
int main (int argc, char *argv[])
{
int r;
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_sigaction = &handler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV,&act,NULL);
if ((r = setjmp(env)) == 0)
    BAD();
else
    printf("proc %d survived SEGMENTATION FAULT: r=%d\n",getpid(), r);

printf("proc %d looping\n",getpid());
while(1);
}

 

 

标签:中断,pid,笔记,学习,进程,int,信号,第六章,define
From: https://www.cnblogs.com/MRC-/p/16841904.html

相关文章