2023-2024-1 20211327 信息安全系统设计与实现 学习笔记9(必做)

发布时间 2023-11-12 15:38:19作者: 沈楗翔

学习笔记9

  • 信号和中断
  • Unix/Linux 中的信号处理
  • 信号处理步骤与异常
  • Linux 中的 IPC
  • 实践过程

信号和中断

“中断”是从I/O设备或协处理器发送到CPU的外部请求,它将CPU从正常执行转移到中断处理。“信号”是发送给进程的请求,将进程从正常执行转移到中断处理。

中断的概念和机制

1.硬件中断:

  • 概念:硬件中断是由计算机系统的硬件设备生成的事件所触发的中断。这些硬件设备可以包括键盘、鼠标、磁盘驱动器、网卡、定时器等。硬件中断通常用于告知CPU发生了某种事件,需要处理或响应。

  • 机制:当硬件设备生成一个中断信号时,它会向中断控制器发送请求(通常使用IRQ线),中断控制器会将该中断请求传递给CPU。CPU会根据中断请求的优先级,暂停当前执行的程序,保存程序状态,跳转到与该中断相关的中断处理程序。中断处理程序负责处理中断事件,然后返回到原始程序的执行点。

2.进程中断:

  • 概念:进程中断是由操作系统内部的事件或条件触发的中断。这些事件包括操作系统调度、进程间通信、异常(如除零错误、无效操作码等)等。进程中断通常用于管理操作系统的任务和进程之间的切换。

  • 机制:当发生进程中断时,操作系统会根据中断的类型,挂起当前运行的进程,保存其状态,然后选择一个新的进程来执行。这实现了多任务处理,允许操作系统在多个进程之间共享CPU时间。

3.人员中断:

  • 概念:人员中断是由计算机用户或外部人员触发的中断。这些中断通常来自外部输入设备,如键盘、鼠标、触摸屏,或者来自网络通信等。

  • 机制:人员中断是用户直接触发的,例如,当用户按下键盘上的键时,键盘会生成一个中断信号,操作系统会响应并传递给相应的应用程序处理。用户的输入将被用于控制程序的执行。

Unix/Linux 中的信号处理

Unix/Linux中的信号处理是一种重要的机制,用于进程间通信和处理异步事件。

1.信号类型:

Unix/Linux系统中有许多不同类型的信号,每个信号都有一个唯一的编号,通常是正整数。一些常见的信号类型包括:

  • SIGINT:终止进程,通常由用户在终端上按下Ctrl+C触发。
  • SIGTERM:终止进程,通常是通过kill命令触发。
  • SIGHUP:终止或重新启动进程,通常在终端断开连接时触发。
  • SIGKILL:强制终止进程,不能被捕获或忽略。
  • SIGSTOP:暂停进程的执行。
  • SIGCONT:继续进程的执行,从暂停状态恢复。
  • someting else

2.信号的来源:

信号可以来自多个来源,包括:

  • 用户:通过终端或命令行工具,用户可以发送信号来控制进程。
  • 操作系统:操作系统可以向进程发送信号,以通知进程发生了某些事件,如子进程终止、硬件错误等。
  • 其他进程:一个进程可以向另一个进程发送信号,以实现进程间通信。

3.进程proc结构体的信号:

Unix/Linux中,每个进程都有一个proc结构体,用于保存有关进程状态的信息,其中包括信号的处理状态。proc结构体中包括:

  • sighand:一个指向信号处理函数的指针,用于定义进程接收信号时的操作。
  • sigpending:一个用于存储未决信号的集合,这些信号在进程处理之前排队等待。
  • signal:一个用于存储已安装的信号处理函数的数组。
  • blocked:一个用于指定被阻止的信号的集合,这些信号不会被处理,而是排队等待。

4.信号处理函数:

每个信号都可以关联一个信号处理函数,用于定义接收到该信号时应采取的操作。信号处理函数可以是用户自定义的函数,也可以是操作系统提供的默认处理函数。用户可以使用signal函数或sigaction函数来为进程安装信号处理函数。

5.安装信号捕捉函数:

在Unix/Linux中,可以使用以下两个主要函数来安装信号处理函数:

  • signal(int signum, void (*handler)(int)):这是一种较早的信号处理函数安装方法,用于指定信号编号和信号处理函数的指针。不推荐使用,因为它在不同系统上的行为不一致。

  • sigaction(int signum, const struct sigaction *act, struct sigaction *oldact):这是一种较新且更强大的信号处理函数安装方法。它允许更精细的控制信号处理,包括指定信号处理函数、标志位和信号掩码等。

  • C语言示例:在C语言中,使用 signal() 函数可以安装信号处理函数。

    #include <stdio.h>
    #include <signal.h>
    
    void signal_handler(int signum) {
        printf("Received signal %d\n", signum);
    }
    
    int main() {
        signal(SIGINT, signal_handler); // 安装SIGINT的信号处理函数
        while (1) {}
        return 0;
    }
    

信号处理步骤

1.进程处于内核模式: 当信号被发送到进程时,进程必须从用户模式切换到内核模式,以便内核能够处理信号。在内核模式下,操作系统可以执行特权操作,例如更改进程的状态和执行信号处理函数。

2.重置用户安装的信号捕捉函数: 如果进程已经为特定信号安装了自定义的信号处理函数,首先,操作系统将保存用户安装的信号处理函数的地址。然后,操作系统将重置信号处理函数为默认行为,这可能包括终止进程或忽略信号,具体取决于信号的默认行为。

3.信号和唤醒: 接下来,操作系统会执行与接收到的信号相关的操作,这包括:

  • a. 终止进程:如果信号的默认行为是终止进程,那么进程将被终止,其状态将变为"终止",并且进程将被从进程表中移除。

  • b. 执行信号处理函数:如果信号处理函数已被安装,操作系统会执行该函数。信号处理函数可以是用户自定义的,用于处理信号时采取特定操作,比如记录信息、清理资源、或采取其他适当的措施。

  • c. 唤醒进程:如果信号没有终止进程,操作系统会将进程从信号等待状态唤醒,以便它能够继续执行。这通常涉及到将进程状态从"等待信号"状态更改为"就绪"状态,以确保进程被调度并执行。

Linux 中的 IPC

1.管道和FIFO(命名管道):

  • 管道:一种单向通信机制,可用于具有父子关系的进程间通信。使用 pipe() 系统调用创建,数据单向流动,通常在父子进程之间使用。
  • FIFO:也称为命名管道,与管道类似,但允许无关进程间的通信。使用 mkfifo() 创建,进程通过打开FIFO文件进行通信。

2. 信号:

  • 信号:用于通知进程发生了某种事件的软件通知机制。可以由操作系统、其他进程或用户发送。使用 kill() 系统调用发送信号,signal()sigaction() 用于注册信号处理函数。

3.System V IPC:

  • 消息队列:允许进程通过消息进行通信,支持多种数据类型。使用 msgget()msgsnd()msgrcv() 等系统调用创建和操作消息队列。
  • 共享内存:允许多个进程访问同一块物理内存。使用 shmget()shmat() 等系统调用来创建和附加共享内存段。
  • 信号量:用于进程同步和互斥,控制进程对共享资源的访问。使用 semget()semop() 等系统调用来操作信号量。

4.POSIX消息队列:

  • POSIX消息队列:类似System V消息队列,但与POSIX标准兼容。使用 mq_open()mq_send()mq_receive() 等函数进行操作。
    5.线程同步机制:

  • 互斥锁:用于防止多个线程同时访问共享资源。使用 pthread_mutex_init()pthread_mutex_lock()pthread_mutex_unlock() 等函数操作互斥锁。

  • 条件变量:用于线程间的条件等待和通知。使用 pthread_cond_init()* pthread_cond_wait()pthread_cond_signal() 等函数。

6.套接字(Socket):

  • 套接字:用于不同主机间进程间通信。包括TCP和UDP套接字,可用于网络通信。使用 socket()bind()connect()send()recv() 等系统调用进行套接字编程。

实践过程