Skip to content

2025年 408 操作系统 第 46 题

操作系统2025年综合题8分

题目

某进程的虚拟地址空间布局如下图所示(阴影部分为未占用区域):

图(文字版):从高地址到低地址依次为

  • 操作系统内核区(最高)
  • 用户栈
  • (未占用阴影)
  • 共享库的存储映射区
  • (未占用阴影)
  • 动态生成的堆(运行时由 malloc 创建)
  • 读/写数据段
  • 只读代码段
  • 未使用区(最低)

image-20260501134945984

有 C 程序:

c
char *ptr;

void main() {
    int length;
    ptr = (char *) malloc(100);
    scanf("%s", ptr);
    length = strlen(ptr);
    printf("length=%d\n", length);
    free(ptr);
}

请回答:

(1) 上述程序执行时,PCB 位于哪个区域?执行 scanf() 等待键盘输入时,进程处于什么状态

(2) main() 函数的代码位于哪个区域?其直接调用的哪些函数的功能需要通过执行驱动程序实现?

(3) 变量 ptr 被分配在哪个区域?若变量 length 没有被分配在寄存器中,则会被分配在哪个区域?ptr 指向的字符串位于哪个区域?

解析

(1)PCB 位置 + scanf 时进程状态

PCB 位于内核区

PCB(Process Control Block)= 进程控制块——是操作系统用来管理进程的核心数据结构(包含 PID、状态、寄存器现场、页表指针、文件表等)。它是操作系统的私有数据,必须放在用户进程不能直接访问的地方——操作系统内核区

编者注(关键区分)

  • PCB 在内核区——用户看不到、改不了
  • 用户栈、堆、代码段都在用户区——用户程序可见、可读写(受权限控制)
  • 这是 CPU "两态分离"在内存布局上的体现

scanf 等待时进程状态:阻塞态

scanf() 等待键盘输入是等待 I/O 完成——属于"等待外部事件"型阻塞。

进程状态变化:

题目问"等待键盘输入时"——这一刻进程处于 阻塞态

(2)main 代码位置 + 哪些函数走驱动

main() 代码 → 只读代码段(.text)

C 编译后所有函数的机器指令都放在程序的"代码段"——也称 .text,运行时被加载到只读代码段。只读是为了防止程序意外或恶意修改自己的代码。

哪些被调用函数需要驱动程序?

逐个分析:

调用功能是否走驱动用什么驱动
malloc(100)分配堆内存通过 brk/mmap 系统调用,但不经过设备驱动
scanf("%s", ptr)从键盘读键盘驱动
strlen(ptr)计算字符串长度纯 CPU 计算
printf("length=%d\n", length)向屏幕输出显示器驱动(终端 / 控制台驱动)
free(ptr)释放堆内存通过 brk/munmap 系统调用,不走设备驱动

scanf()printf() 需要驱动程序实现

编者注(关键概念区分)

  • 系统调用 ≠ 设备驱动调用:malloc 走系统调用(brk)但不涉及驱动;scanf 既走系统调用(read)又触发设备驱动(键盘驱动)
  • "涉及外设的"才需要驱动:键盘、屏幕、磁盘、网卡都是外设;内存分配是 CPU + MMU 的事,不算外设

(3)三个变量的存储区域

变量在哪理由
ptr读/写数据段(.data/.bss)char *ptr;全局变量(在 main 外定义),全局变量进数据段
length用户栈int length; 是 main 内部的局部变量,局部变量入栈(除非编译器优化进寄存器)
ptr 指向的字符串堆区malloc(100) 在堆上分配;ptr 只是栈外的"指针",指针变量指针指向的目标位置可以不同

编者注(典型陷阱:指针 vs 指针指向的目标)

c
char *ptr;              // ptr 自己在 .data
ptr = malloc(100);       // ptr 指向 heap 的某 100 字节

这里有 3 个东西容易搞混:

  1. ptr 这个变量本身(4 / 8 字节的指针,在数据段)
  2. ptr 的值(堆上某个地址,如 0x7f1234)
  3. ptr 指向的内容(堆上 100 字节)

题目问"ptr 在哪"是问 1,问"ptr 指向的字符串在哪"是问 3。两者位置不同,是这道题的核心考察点。

如果 ptr 是局部变量 char *ptr; void main() { ptr = ... }——则 ptr 在栈上,不在数据段。本题里 ptr 在 main 外面定义,所以是全局变量。

编者注(关于内存布局的总结)

内容谁创建谁释放
内核区PCB、内核代码 / 数据OSOS
用户栈局部变量、函数参数、返回地址编译器自动编译器自动
共享库映射libc 等动态库加载器加载器
malloc / new 分配的对象程序员(malloc)程序员(free)
读/写数据段全局变量、静态变量链接器进程退出时
只读代码段函数代码、字符串字面量链接器进程退出时

Linux 严格按这个布局,本题的图是简化版(把 .data 和 .bss 合成"读/写数据段",省了 PLT/GOT 等小区域)。考研掌握这张表就够了。

最后更新:

⚠️ 这道题暂未配可视化,欢迎在 CodeBrick 反馈区告诉我们你想看哪道题