信息安全系统设计与实现学习笔记9

学习笔记 9

一、知识点归纳以及自己最有收获的内容

1. 信号和信号处理

进程的概念

  • 一个“进程”是一系列活动,包括从事日常事物的人、在用户模式或内核模式下运行的Unix/Linux进程以及执行机器指令的CPU。

中断

  • 中断可分为三类:来自硬件的中断、来自其他人的中断、自己造成的中断。
  • 人员中断可根据紧急程度分为不可屏蔽(NMI)和可屏蔽。
  • 进程中断分为来自硬件、其他进程、自己造成的中断。
  • 硬件中断可来自硬件、其他处理器、进程的陷阱错误。

进程的陷阱错误

  • 进程可能自己造成中断,由CPU识别为异常的错误引起,如除以0、无效地址等。
  • 进程遇到异常时会陷入操作系统内核,将陷阱原因转换为信号编号,并将信号发送给自己。
  • 如果在用户模式下发生异常,则进程的默认操作是终止,可选地进行内存转储进行调试。
  • 如果在内核模式下发生陷阱,原因可能是硬件错误或内核代码中的漏洞,这时内核无法处理。

2. Unix/Linux中的信号处理

信号类型

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

信号来源

  • 来自硬件的中断信号,来自异常的信号,来自其他进程的信号。

信号处理步骤

  1. 当某进程处于内核模式时,会检查信号并处理未完成的信号。
  2. 重置用户安装的信号捕捉函数,用于处理用户代码中的陷阱错误。
  3. 信号和唤醒:在Unix/Linux内核中有两种SLEEP进程:深度休眠进程和浅度休眠进程。

二、实践内容与截图

实践1

  • 运行以下代码:
#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)
        ;
}
posted @ 2023-11-12 14:09  20211225高端  阅读(12)  评论(0)    收藏  举报