嵌入式大厂面经 Linux进程管理常见面试题(持续更新中!)

这是一个嵌入式大厂面试题专栏,每天更新高频面试题。专栏将包含题目描述、详细解析、相关知识点扩展以及实际代码示例。内容涵盖操作系统、驱动开发、通信协议等核心领域,并结合实际项目经验进行分析。每道题目都会附带面试官可能的追问方向,帮助大家更好地准备面试!

Linux进程调度和进程创建相关面试题

一、Linux进程调度基础

1. 进程调度的概念

Linux进程调度是操作系统核心功能之一,负责决定哪个进程在CPU上运行,以及运行多长时间。调度器的目标是在保证公平性的同时,最大化系统吞吐量和最小化响应时间。

2. Linux调度器的发展

  • O(1)调度器:Linux 2.6早期版本使用,常数时间复杂度
  • CFS(完全公平调度器):从Linux 2.6.23开始引入,现在的主流调度器
  • 实时调度器:用于实时任务,包括SCHED_FIFO和SCHED_RR策略
  • BFS(脑残调度器)MuQSS:第三方调度器,针对桌面响应优化

3. CFS调度器原理

CFS基于"虚拟运行时间"概念,追踪每个进程的运行时间:

  • 使用红黑树数据结构组织进程
  • 进程的虚拟运行时间越小,获得CPU的优先级越高
  • 进程运行时,其虚拟运行时间增加
  • 目标是让所有进程的虚拟运行时间接近

4. 调度策略和优先级

Linux支持多种调度策略:

  • SCHED_OTHER(CFS):普通进程的默认策略
  • SCHED_BATCH:批处理进程,不需要交互
  • SCHED_IDLE:优先级最低的进程
  • SCHED_FIFO:实时进程,先进先出,不会被抢占(除非被更高优先级进程)
  • SCHED_RR:实时进程,时间片轮转

优先级系统:

  • nice值:范围-20到19,值越小优先级越高,默认为0
  • 实时优先级:范围1-99,值越大优先级越高

二、进程创建相关系统调用

1. fork系统调用

fork()是Unix/Linux中创建进程的传统方法:

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

特点

  • 创建调用进程的副本(子进程)
  • 子进程获得父进程数据空间、堆、栈的副本
  • 父子进程共享代码段(只读)
  • 采用写时复制(Copy-On-Write)技术优化内存使用
  • 返回值:父进程中返回子进程PID,子进程中返回0,失败返回-1

示例

#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid = fork();
    
    if (pid < 0) {
        // 创建失败
        perror("fork failed");
        return 1;
    } else if (pid == 0) {
        // 子进程
        printf("子进程,PID: %d,父进程PID: %d\n", getpid(), getppid());
    } else {
        // 父进程
        printf("父进程,PID: %d,子进程PID: %d\n", getpid(), pid);
    }
    
    return 0;
}

2. vfork系统调用

vfork()fork()的一种特殊形式:

#include <unistd.h>
pid_t vfork(void);

特点

  • 创建进程的目的是执行exec系列函数
  • 子进程与父进程共享地址空间(不使用写时复制)
  • 父进程会被挂起,直到子进程调用exec或exit
  • 子进程必须小心不修改共享的变量
  • 现代系统中,fork的性能已经很好,vfork使用较少

示例

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    pid_t pid = vfork();
    
    if (pid < 0) {
        // 创建失败
        perror("vfork failed");
        return 1;
    } else if (pid == 0) {
        // 子进程
        printf("子进程,PID: %d\n", getpid());
        // 子进程必须调用exec或exit
        _exit(0);  // 注意使用_exit而非exit
    } else {
        // 父进程
        printf("父进程,PID: %d,子进程PID: %d\n", getpid(), pid);
    }
    
    return 0;
}

3. clone系统调用

clone()是Linux特有的系统调用,提供更细粒度的控制:

#define _GNU_SOURCE
#include <sched.h>
int clone(int (*fn)(void *), void *stack, int flags, void *arg, ...);

特点

  • 允许选择父子进程间共享的资源(如文件描述符、信号处理等)
  • 是实现线程的基础(pthread库在底层使用clone)
  • 通过flags参数控制共享程度
  • 常用flags: CLONE_FILES:共享文件描述符表CLONE_FS:共享文件系统信息CLONE_VM:共享内存空间CLONE_SIGHAND:共享信号处理函数

示例

#define _GNU_SOURCE
#include <stdio.h>
#include <sched.h>
#include <stdlib.h>
#include <unistd.h>

#define STACK_SIZE (1024 * 1024)  // 1MB栈空间

// 子进程执行的函数
int child_func(void *arg) {
    printf("子进程,P

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

嵌入式面试八股文全集 文章被收录于专栏

这是一个全面的嵌入式面试专栏。主要内容将包括:操作系统(进程管理、内存管理、文件系统等)、嵌入式系统(启动流程、驱动开发、中断管理等)、网络通信(TCP/IP协议栈、Socket编程等)、开发工具(交叉编译、调试工具等)以及实际项目经验分享。专栏将采用理论结合实践的方式,每个知识点都会附带相关的面试真题和答案解析。

全部评论

相关推荐

评论
1
3
分享

创作者周榜

更多
牛客网
牛客企业服务