信息安全系统设计与实现第三章学习笔记

发布时间 2023-10-17 19:51:02作者: 20211210王宇轩

一、知识点归纳

1. 多任务处理

多任务处理是计算机系统中的重要概念,它允许系统同时执行多个任务,提高了系统资源的利用率和响应速度。在多任务处理中,有几个重要的概念和技术需要进一步了解:

  • 并发(Concurrency):并发是指多个任务在时间上重叠执行的能力。虽然在单处理器系统中一次只能执行一个任务,但通过快速切换任务的执行上下文,可以让用户感觉到多个任务在同时执行。
  • 并行(Parallelism):并行是指多个任务在不同的处理器或核心上同时执行。多处理器系统可以实现真正的并行处理,提高了系统的性能。
  • 上下文切换(Context Switching):上下文切换是从一个任务切换到另一个任务时保存和恢复任务的执行环境的过程。这是多任务处理中必不可少的操作,它确保了任务之间的独立性。
  • 操作系统的角色:操作系统在多任务处理中起着关键的作用,它负责任务的调度、资源分配、上下文切换等管理工作,以确保任务之间的合理竞争和协作。

2. 进程

进程是操作系统中的基本执行单元,每个进程都有自己的内存空间和执行环境。在进程管理中,还有一些重要的概念和操作:

  • 进程控制块(PCB):进程控制块是操作系统维护的数据结构,用于描述和管理进程的状态和信息。它包含了进程的标识符、状态、优先级、程序计数器、寄存器状态等信息。
  • 进程调度:操作系统通过进程调度算法来确定下一个执行的进程。常见的调度算法包括先来先服务(FCFS)、最短作业优先(SJF)、轮转调度(Round Robin)等。
  • 进程同步:多个进程之间需要协作和同步,以避免竞争条件和数据不一致性。信号量、互斥锁、条件变量等同步机制用于实现进程之间的协作。

3. 多任务处理系统

多任务处理系统通常由多个组件组成,包括数据结构、汇编代码、队列操作函数等。这些组件协同工作以支持多任务处理。

  • 数据结构:在多任务处理系统中,常常需要定义各种数据结构来管理进程、任务队列、事件等信息。这些数据结构用于存储和操作系统内核中的关键信息。
  • 汇编代码:汇编代码通常用于实现进程上下文切换,确保进程可以在合适的时机被调度执行。
  • 队列操作函数:队列操作函数用于管理任务队列,包括进程就绪队列、等待队列等。enqueue()函数可以按优先级将进程添加到队列中,确保高优先级任务得到及时执行。

4. 进程同步

进程同步是多任务处理中的一个重要问题,它涉及到如何协调多个进程的执行,以避免竞争和冲突。在进程同步中,有几个关键概念:

  • 睡眠模式:当一个进程需要等待某个事件发生时,它可以进入睡眠模式。这是通过将进程的状态设置为休眠,并等待事件的发生来实现的。
  • 唤醒操作:当事件发生时,另一个进程或中断处理程序可以调用唤醒函数,将等待中的进程从休眠状态唤醒,继续执行。
  • 进程终止:进程可以以正常终止或异常终止的方式结束执行。正常终止是通过调用exit()系统调用来实现的,而异常终止可能涉及信号处理。

5. 进程管理

进程管理是操作系统的核心功能之一,它包括进程创建、销毁、调度、同步等操作。在进程管理中,还有一些需要考虑的因素:

  • 进程家族树:进程可以以树状结构组织,其中父进程可以创建子进程,形成家族关系。这种组织有助于进程管理和资源隔离。
  • 进程同步函数:操作系统需要提供进程同步函数,如ksleep()和kwakeup(),以确保进程能够等待事件的发生和唤醒等待中的进程。
  • 进程终止和等待:进程可以以不同方式终止,而其他进程可以使用kwait()等待子进程的终止,并获取其终止状态。

6. Unix/Linux中的进程

Unix/Linux操作系统中的进程管理是非常重要的,它影响着系统的稳定性和性能。在Unix/Linux中,进程的管理方式包括以下关键点:

  • 进程来源:Unix/Linux系统在启动时创建一个初始进程(PID=0),然后通过复制(fork)操作创建其他进程。这些进程可以是守护进程、登录进程、用户进程等。
  • 守护进程:守护进程是在后台运行的进程,通常用于提供系统服务。它们不与用户交互,例如Web服务器、数据库服务器等。
  • 登录进程:登录进程负责

处理用户登录,每个终端通常有一个登录进程。登录进程会打开与终端相关联的文件流,如stdin、stdout、stderr。

  • sh进程:用户登录后,通常会启动一个shell进程,它负责解释和执行用户的命令。Shell进程会创建子进程来执行用户命令,然后等待子进程的终止状态。
  • 进程执行模式:进程可以以不同的执行模式运行,包括中断、陷阱和系统调用。中断和陷阱用于响应外部事件和错误条件,而系统调用用于执行内核函数。

7. 进程管理的系统调用

在Unix/Linux系统中,进程管理涉及许多系统调用,这些系统调用用于创建、销毁、管理进程。一些重要的系统调用包括:

  • fork():创建子进程,复制父进程的地址空间和状态。
  • exec():用新程序替换当前进程的地址空间,执行新程序。
  • wait():等待子进程的终止,并获取子进程的终止状态。
  • exit():终止当前进程的执行,并返回终止状态。
  • getpid():获取当前进程的PID。
  • kill():向指定进程发送信号,触发不同的处理行为。
  • pipe():创建管道,用于进程间通信。
  • dup()和dup2():复制文件描述符,用于I/O重定向。

这些系统调用构成了进程管理的基础,允许程序员编写复杂的多进程应用程序,并有效地管理进程的行为和资源。

8. I/O重定向

I/O重定向是Unix/Linux系统中的一个强大功能,它允许进程将标准输入、标准输出和标准错误输出定向到文件或其他进程。这对于处理输入和输出非常有用。

  • 文件流和文件描述符:文件流是与打开文件相关联的抽象概念,而文件描述符是在操作系统内部用于标识文件流的整数值。标准输入、标准输出和标准错误输出的文件描述符分别是0、1、2。
  • 管道和管道命令:管道是一种进程间通信机制,它允许一个进程的输出直接成为另一个进程的输入。管道命令(例如"cmd1 | cmd2")用于创建管道并连接多个进程,实现数据流的传递。

二、ChatGpt提问






三、实践及代码托管

(1)创建子进程,验证父子关系

#include <stdio.h>
#include <unistd.h> // 添加这行头文件
int main() {
    int pid;
    printf("THIS Is %d MY PARENT=%d\n", getpid(), getppid());
    pid = fork(); // fork syscall; parent returns child pid,
    if (pid) { // PARENTEXECUTES THIS PART
        printf("THIS IS PROCESS %d CHILD PID=%d\n", getpid(), pid);
    } else {    // child executes this part
        printf("this is process %d parent=%d\n", getpid(), getppid());
    }
    return 0;
}


(2)创建子进程,父子并发执行

#include <stdio.h>
#include <unistd.h> // 添加这行头文件
int main() {
    int pid = fork(); // fork a child
    if (pid) { // PARENT
        printf("PARENT %d CHILD=%d\n", getpid(), pid);
        // sleep(1);    // sleep 1 second ==> let child run next
        printf("PARENT %d EXIT\n", getpid());
    } else {
        // child
        printf("child %d start my parent=%d\n", getpid(), getppid());
        sleep(2); // sleep 2 seconds => let parent die first
        printf("child %d exit my parent=%d\n", getpid(), getppid());
    }
    return 0;
}


代码已托管至gitee,链接:https://gitee.com/wang-yuxuan333/123.git
具体详见tryfork.txt ordexe.txt

四、问题及解决

编写代码时出现未调用函数库问题,通过询问ChatGpt成功解决。