当前位置:首页>Linux>从0开始掌握Linux进程(1)

从0开始掌握Linux进程(1)

  • 2026-10-11 06:04:09
从0开始掌握Linux进程(1)

一、冯诺依曼体系结构:进程运行的物理基础

1.1 为什么需要冯诺依曼体系?

历史背景:在计算机诞生初期,ENIAC等早期计算机采用"存储程序"概念之前,每次计算都需要重新接线,效率极低。1945年,冯诺依曼提出了"存储程序"概念,将程序和数据统一存储在内存中,彻底改变了计算机的工作方式。

解决的问题: - 程序可重复执行,无需每次重新接线 - 数据和指令统一管理,提高效率 - 实现自动执行,解放人力

1.2 冯诺依曼体系的核心组成

输入设备 → [存储器(内存)] → CPU(运算器+控制器) → [存储器(内存)] → 输出设备

关键特性: - 存储器指的是内存,不是硬盘等外存 - CPU只能直接访问内存,不能直接读写外设 - 所有设备都通过内存交互,内存是数据交换中心

1.3 实际应用:QQ聊天的数据流

以QQ聊天为例,理解冯诺依曼体系的数据流:

你的输入(键盘) → 内存 → CPU处理 → 内存 → 网卡发送                ↓对方网卡接收 → 内存 → CPU处理 → 内存 → 显示器输出

实践启示:理解数据流有助于优化程序性能,减少不必要的内存拷贝。


二、操作系统:进程的管理者

2.1 操作系统的诞生与定位

历史起源:早期计算机需要人工管理硬件资源,效率低下且容易出错。1960年代,操作系统诞生,目的是自动化管理软硬件资源,为用户提供统一的执行环境。

核心定位: - 向下:管理所有硬件和软件资源 - 向上:为应用程序提供良好执行环境

2.2 管理的本质:描述与组织

操作系统管理硬件的方法,也是管理进程的方法:

管理哲学:

1. 描述:用struct结构体描述对象属性2. 组织:用链表等高效数据结构组织对象

实例:学校管理学生的类比 - 描述学生:姓名、学号、成绩等属性(struct) - 组织学生:按班级、年级组织(链表/树)

2.3 系统调用与库函数

设计初衷:操作系统需要保护硬件安全,不能让用户直接操作硬件。因此提供有限的接口——系统调用。

演进过程:

系统调用(基础) → 封装 → 库函数(易用) → 应用程序

实际应用:

// 系统调用:getpid() - 获取进程ID#includepid_tgetpid(void);// 库函数:printf() - 封装了write系统调用#includeprintf("Hello World\n");

三、进程概念:从程序到执行实体

3.1 进程概念的诞生

问题背景:早期计算机一次只能运行一个程序,资源利用率极低。多道程序设计出现后,需要同时运行多个程序,如何区分和管理这些正在运行的程序?

解决方案:引入"进程"概念——程序的执行实例。

定义演进: - 课本定义:程序的一个执行实例 - 内核视角:分配系统资源的实体 - 现代定义:进程 = 内核数据结构(task_struct) + 程序代码和数据

3.2 PCB:进程控制块

设计目的:操作系统需要"描述"进程,因此设计了PCB(Process Control Block)。

Linux实现:task_struct结构体

// task_struct包含的关键信息struct task_struct {    // 标识符:唯一标识进程    pid_t pid;    // 状态:运行、睡眠、停止等    volatile long state;    // 优先级:决定调度顺序    int prio;    // 程序计数器:下一条指令地址    unsigned long eip;    // 内存指针:代码、数据位置    struct mm_struct *mm;    // 上下文数据:寄存器内容    struct thread_info thread_info;    // I/O状态:打开的文件等    struct files_struct *files;    // 记账信息:CPU时间等    cputime_t utime, stime;};

组织方式:所有进程以双链表形式存在于内核中。

3.3 进程查看与操作

查看进程:

# 方法1:通过/proc文件系统ls /proc/[pid]# 方法2:使用ps命令ps aux | grep process_name# 方法3:使用top命令(动态)top

获取进程ID:

#include#includeintmain(){    printf("进程ID: %d\n", getpid());    printf("父进程ID: %d\n", getppid());    return 0;}

3.4 fork:进程创建

设计初衷:Unix系统需要创建新进程执行新任务,fork是最基础的进程创建机制。

核心特性: - fork有两个返回值:父进程返回子进程PID,子进程返回0 - 父子进程代码共享,数据各自私有(写时拷贝)

示例代码:

#include#include#includeintmain(){    pid_t pid = fork();    if (pid < 0) {        perror("fork失败");        return 1;    }    else if (pid == 0) {        // 子进程        printf("我是子进程,PID: %d\n", getpid());    }    else {        // 父进程        printf("我是父进程,PID: %d,子进程PID: %d\n", getpid(), pid);    }    return 0;}

输出示例:

我是父进程,PID: 1234,子进程PID: 1235我是子进程,PID: 1235

最新文章

随机文章