《操作系统导论》学习笔记(二):CPU虚拟化(进程)

本文是《操作系统导论》的学习笔记,主要探讨进程的虚拟地址空间、用户空间分区和内核空间的进程控制块。介绍了进程的创建过程,包括虚拟地址空间的构成、用户空间的栈和堆分区,以及进程控制块中的关键信息。此外,还讲解了子进程的创建(fork())、等待(wait())和执行新程序(exec())的原理,以及进程API的作用和系统调用与API的关系。
摘要由CSDN通过智能技术生成

《操作系统导论》学习笔记(一):操作系统概览

进程


程序:指令和数据的集合,一般作为目标文件保存在磁盘中。
进程:程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。

可执行程序位于磁盘中,需要将静态程序加载到内存生成动态的进程,CPU才可以不停地取指执行。进程的创建过程涉及到许多陌生的概念,诸如进程控制块、进程队列、用户空间等待等,下面将从虚拟地址空间开始阐述。

1. 虚拟地址空间

在这里插入图片描述
虚拟地址空间:在多任务操作系统中,每个进程都运行在属于自己的内存沙盘中,这个沙盘就是虚拟地址空间(virtual address space)。虚拟地址空间由内核空间(kernel space)和用户空间(user space)两部分组成。

下图为内核空间和用户空间的具体构成:
在这里插入图片描述

2. 用户空间分区

程序包含代码及数据,编译链接生成的可执行文件时汇编形式,装载到内存中是二进制文件。程序是通过变量访问数据,但在二进制下是没有变量的概念,只能通过内存地址访问数据。如果全部变量都通过地址访问,这样是低效且不现实的。因而,需要根据不同变量的性质进行分区

  • 局部变量内容短小,需要频繁访问,但是生命周期很短,通常只在一个方法内存活,就专门从内存划分出一块较小区域命名为栈(stack),由编译器分配与回收,效率高。
  • 较大的结构体可能不需要太频繁的访问,但生命周期较长,通常很多个方法中都会用到,就划出另一较大区域命名为堆(heap),由程序员自主使用内存API函数分配回收。

在这里插入图片描述
在这里插入图片描述

3. 内核空间的进程控制块

操作系统在创建进程时会在内核空间配备一个进程控制块(PCB),包含描述进程当前情况及管理进程全部信息的数据结构。在Linux操作系统中的进程控制块实际是一个task_struct结构体,放在sched.h,以下简要介绍。
在这里插入图片描述
(1) 进程状态(process state):进程的核心运行状态包括就绪(Ready)、阻塞(Blocked)及运行(Running)。

enum proc_state {
    READY, RUNNING, READY };

在这里插入图片描述
就绪(Ready):进程拥有运行所需的所有资源,等待分配CPU。
运行(Running):进程运行在CPU上,即CPU正在运行该进程包含的指令。
阻塞(Blocked)/等待(Waiting):进程在运行时发生CPU以外事件的请求(如I/O请求)从而放弃CPU使用权。

《操作系统导论》实验一:模拟进程状态转换

(2) 进程标识符(process identifier/number):描述本进程的唯一标识符,用来区别其他进程。

int pid;		// Process ID

(3) 处理机状态:进程切换时的入口地址及需要保存的信息,包括程序计数器、通用寄存器、程序状态字和用户栈指针。

// the registers xv6 will save and restore
// to stop and subsequently restart a process
struct context {
   
  int eip;		// 程序计数器(PC),存放下一个CPU指令存放的内存地址
  int ebx;		// 基址寄存器, 在内存寻址时存放基地址
  int ecx;		// 计数器(counter),loop循环的内定计数器
  int edx;		// 用来放整数除法产生的余数
  int esi;		// 源变址寄存器
  int edi;		// 目的变址寄存器
  int esp;		// 栈指针寄存器
  int ebp;		// 基址指针寄存器
};

(4)内存限制(memory limits)

char *mem;		// Start of process memory
uint sz;		// Size of process memory

(5)打开文件列表

struct file *ofile[NOFILE]; // Open files

(6) 进程指针(pointer):采用指针将进程控制块之间相互链接
在这里插入图片描述
进程链表组织方式是系统设置就绪队列头指针、阻塞队列头指针、运行队列头指针,按照进程的状态将进程的PCB挂在对应头指针后组成队列。

下面是进程的创建过程:
在这里插入图片描述
创建进程时,操作系统为进程生成唯一的进程控制块(PCB)并挂在进程队列,用户空间开辟内存,装入程序的变量及代码,栈内保存 main() 的参数argc/argv,清空寄存器内容,main()入口地址送到程序计数器PC;CPU执行程序main()的指令,遇到return语句返回操作系统;操作系统释放进程内容,并将进程从进程队列中移除。

子进程

1. f o r k ( ) fork() fork() 创建子进程

(1) 头文件及函数原型

#include <unistd.h>
#define int pid_t 
pid_t fork( void);

返回值:成功调用一次则返回两个值,父进程返回子进程PID,子进程返回0;调用失败则返回-1。

(2) 函数说明
主函数main()运行时会自动创建进程,称为父进程;fork()系统调用用于创建一个新进程,称为子进程。创建子进程时,子进程会在内核中拥有自己的进程控制块(task_struct),从而拥有不同于父进程的PID。但同时,子进程复制父进程其余一切(堆栈、代码段等),而fork()作为系统调用保存在父进程和子进程的栈中,因而会返回两次,产生两个返回值。
在这里插入图片描述

// p1.c
#include
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值