MST

星途 面试题库

面试题:C语言结构体与联合体在复杂场景下的应用

在一个操作系统内核模拟项目中,需要设计一个数据结构来管理系统中的进程信息。进程信息包括进程ID、进程状态(枚举类型)、内存使用情况(结构体)、父子进程关系(通过结构体指针表示)。同时,为了节省内存,对于一些小型进程,希望可以复用部分内存空间,这就需要用到联合体。请设计并实现这样的数据结构,并编写相关的初始化、添加进程、删除进程的函数,要充分考虑数据的一致性和内存管理,确保代码健壮且高效。
22.4万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义进程状态枚举类型
typedef enum {
    RUNNING,
    WAITING,
    TERMINATED
} ProcessStatus;

// 定义内存使用情况结构体
typedef struct {
    size_t total;
    size_t used;
} MemoryUsage;

// 定义进程结构体,使用联合体复用内存
typedef union {
    struct {
        int pid;
        ProcessStatus status;
        MemoryUsage memUsage;
        struct Process* parent;
        struct Process* children;
    } largeProcess;
    struct {
        int pid;
        ProcessStatus status;
    } smallProcess;
} ProcessUnion;

// 定义最终的进程数据结构
typedef struct Process {
    ProcessUnion data;
    int isLarge;
    struct Process* next;
} Process;

// 初始化进程数据结构
Process* createProcess(int pid, ProcessStatus status, MemoryUsage memUsage, Process* parent, int isLarge) {
    Process* newProcess = (Process*)malloc(sizeof(Process));
    if (newProcess == NULL) {
        perror("malloc");
        return NULL;
    }
    if (isLarge) {
        newProcess->data.largeProcess.pid = pid;
        newProcess->data.largeProcess.status = status;
        newProcess->data.largeProcess.memUsage = memUsage;
        newProcess->data.largeProcess.parent = parent;
        newProcess->data.largeProcess.children = NULL;
    } else {
        newProcess->data.smallProcess.pid = pid;
        newProcess->data.smallProcess.status = status;
    }
    newProcess->isLarge = isLarge;
    newProcess->next = NULL;
    return newProcess;
}

// 添加进程到链表
void addProcess(Process** head, int pid, ProcessStatus status, MemoryUsage memUsage, Process* parent, int isLarge) {
    Process* newProcess = createProcess(pid, status, memUsage, parent, isLarge);
    if (*head == NULL) {
        *head = newProcess;
    } else {
        Process* current = *head;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = newProcess;
    }
}

// 删除进程并处理父子关系
void deleteProcess(Process** head, int pid) {
    Process* current = *head;
    Process* prev = NULL;

    while (current != NULL && current->data.largeProcess.pid != pid) {
        prev = current;
        current = current->next;
    }

    if (current == NULL) {
        return;
    }

    if (prev == NULL) {
        *head = current->next;
    } else {
        prev->next = current->next;
    }

    if (current->isLarge) {
        // 处理父进程和子进程关系,这里简单示例,实际可更复杂
        if (current->data.largeProcess.parent != NULL) {
            // 假设父进程有链表管理子进程,需要从父进程子进程链表移除当前进程
        }
        if (current->data.largeProcess.children != NULL) {
            // 处理子进程,可递归删除子进程
        }
    }
    free(current);
}

int main() {
    Process* processList = NULL;
    MemoryUsage memUsage = {1024, 512};
    addProcess(&processList, 1, RUNNING, memUsage, NULL, 1);
    addProcess(&processList, 2, WAITING, memUsage, processList, 0);
    deleteProcess(&processList, 1);
    return 0;
}
  1. 数据结构设计
    • 定义了ProcessStatus枚举类型表示进程状态。
    • MemoryUsage结构体表示内存使用情况。
    • ProcessUnion联合体用于复用内存,根据进程大小选择不同的结构体布局。
    • 最终的Process结构体包含联合体、是否为大进程的标志和链表指针。
  2. 初始化函数createProcess函数根据传入的参数初始化进程数据结构,并分配内存。
  3. 添加进程函数addProcess函数在链表末尾添加新的进程。
  4. 删除进程函数deleteProcess函数在链表中找到并删除指定pid的进程,同时处理父子进程关系。

注意,以上代码仅为基本实现,在实际操作系统内核模拟中,父子进程关系的处理可能需要更复杂的数据结构和逻辑。