【Linux】进程初阶(1)——基本进程理解

作者:终焉代码日期:2025/11/8

目录

前言

1.1进程基本理解

1.2进程描述

1.3查看进程

1.4通过系统调用的基本进程操作

1.4.1通过系统调用获取pid

1.4.2通过系统调用创建进程


前言

操作系统对计算机软件与硬件进行管理的方式是先描述再组织,而PCB就是那个"描述",那到底什么是PCB?PCB又在描述什么呢?更多Linux学习内容看准Linux专栏


1.1进程基本理解

在操作系统中,我们运行的一个个软件本质上都是程序。例如我们在windows上打开浏览器时,本质是运行一个.exe的可执行文件。当程序在计算机上动态运行时,操作系统为了方便管理程序的运行,会用一个叫进程控制块(Process Control Block)的数据结构存储管理程序运行时所需要的属性信息,再用链表将PCB存储起来,进而对进程进行管理,以此做到"先描述,再组织"。因此可以认为进程就是PCB数据结构+程序本身的代码和数据。

这里需要注意的是单一的程序不能被称为进程,当程序未被执行时本质还是普通文件中的一个数据。只有当程序被执行,加载到计算机内存中,操作系统能通过PCB对执行程序进行控制时,才能被称为进程。

1.2进程描述

对进程进行描述也就是记录进程信息是进程控制块(PCB),PCB数据结构中存储的信息就是进程的属性信息。在不同操作系统中对应的PCB数据结构会有不同,而在Linux中PCB数据结构对应的是task_struct结构体。

task_struct结构体本质是PCB的一种,是Linux内核中的一种数据结构,它会被加载到内存中并且包含Linux操作系统中进程的信息。

task_struct基本内容简介

• 标示符(Process Identifier):描述本进程的唯⼀标示符,⽤来区别其他进程。
• 状态: 任务状态,退出代码,退出信号等。
• 优先级: 相对于其他进程的优先级。
• 程序计数器: 程序中即将被执⾏的下⼀条指令的地址。
• 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
• 上下⽂数据: 进程执⾏时处理器的寄存器中的数据。
• I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使⽤的⽂件列表。
• 记账信息: 可能包括处理器时间总和,使⽤的时钟数总和,时间限制,记账号等。
• 其他信息
• 具体详细信息后续会介绍

进程标示符与进程状态在后文会详细展开,下面简单介绍后面内容。

优先级:进程在运行时需要操作系统对其分配硬件资源(内存,CPU等),进程优先级就代表了分配资源的优先级。优先级主要涉及后续进程调度部分。

程序计数器:程序计数器本质是一个寄存器,用来指示程序下一步应该执行哪里。简单举例来说,若一个程序有500行,程序计数器记录程序已经执行到哪一行,进而计算机通过程序计数器来判断下一步程序应该执行哪一行。后面主要与进程切换有关。

内存指针:储存程序运行时的地址,方便操作系统对程序进行管理。

记账信息:类似于表示进程已经调度的时间。

后续更深入的内容会在各部分单独讲解。

1.3查看进程

在查看进程之前,我们需要获取到我们想要查看的那个进程的标识符(pid),pid作为描述进程的唯一标识符,用来区分其他进程。在获取到pid之后,我们可以查看在/proc文件夹下对应pid进程的进程信息。例如我们要查看pid为1的进程信息:

ls /porc/1

当然我们也可以查看/proc文件夹下所有的进程信息(所有正在运行的程序)

ls /proc/

1.4通过系统调用的基本进程操作

1.4.1通过系统调用获取pid

系统调用简而言之就是操作系统内置的库函数,最基本的,我们可以通过系统调用来获取进程的pid。Linux获取pid的库函数是getpid,可以通过man手册来查看其api。

man getpid

可以看到getpid的返回类型为pid_t,不需要参数。这时通过自己编写程序来验证getpid是否真的能获取到pid:

1#include<stdio.h>
2#include<sys/types.h>
3#include<unistd.h>
4
5int main()
6{
7    while(1)
8    {
9        pid_t pid = getpid();
10        printf("this is a process and pid is : %d\n", pid);
11        pid_t ppid = getppid();
12        printf("this is a process and ppid is : %d\n", ppid);
13        sleep(1);
14        //fflush(stdout);
15    }
16
17    return 0;
18}

这里通过死循环让程序一直保持运行状态,即进程运行状态,随后打印该进程的pid。来看看运行结果

可以看到该程序进程的pid是21718,随后再看看程序运行过程中用proc了查看该进程信息

可以看到这时是可以查看到的,那如果停止程序运行呢?

可以看到程序停止运行之后该pid进程就没有了,说明getpid获取的就是当前程序的pid。

而当我们用man手册了查询pid时,可以看到还有一个叫getppid的函数。ppid同样也是task_strcut结构体中储存的信息之一,ppid代表父进程的pid,也就是当前程序父进程的标识符。

pid与ppid的用法类似:

1#include<stdio.h>
2#include<sys/types.h>
3#include<unistd.h>
4
5int main()
6{
7    while(1)
8    {
9        pid_t pid = getpid();
10        printf("this is a process and pid is : %d\n", pid);
11        pid_t ppid = getppid();
12        printf("this is a process and ppid is : %d\n", ppid);
13        sleep(1);
14        //fflush(stdout);
15    }
16
17    return 0;
18}

1.4.2通过系统调用创建进程

此时可以看到该进程的父进程pid就是26918,那到底什么是父进程呢?

我们先来看看pid为26918的进程是什么:利用ps -p <PID> -o comm命令可以查看该pid进程在系统中的命名

ps -p 26918 -o comm

可以看到pid为26918的进程在系统中叫作bash,bash在Linux系统中就是我们看见的命令行提示器,就是Linux系统的shell外壳。也就是说我们自己程序创建的进程的父进程就是bash,当我们在bash中运行程序编译好的可执行文件时,同时也创建了新的进程,我们自己程序的进程就成为了bash的子进程。

所以当一个进程在运行过程中创建了一个新的进程时,这个新进程就是原进程的子进程,原进程就是新进程的父进程。那在Linux中如何创建进程呢?

创建进程属于系统层面的操作,因此需要系统调用。在Linux中创建子进程的系统调用函数为fork:

先不管其他的,我们先来创建一个子进程看一看:

1#include<stdio.h>
2#include<sys/types.h>
3#include<unistd.h>
4
5int main()
6{
7    pid_t pid1 = getpid();
8    printf("原pid为%d\n", pid1);
9
10    fork();
11
12    pid_t pid2 = getpid();
13    pid_t ppid = getppid();
14
15    while(1)
16    {
17        printf("这个进程的pid为:%d,ppid为:%d\n", pid2, ppid);
18        sleep(2);
19    }
20
21    return 0;
22}

运行结果:

可以看到这里就是创建子进程成功了,再进一步了解fork:

这里for返回的是pid_t类型,但如果创建子进程成功父进程就是返回子进程的pid,而子进程则返回0;若失败则返回-1。先来验证下正确性:

1#include<stdio.h>
2#include<sys/types.h>
3#include<unistd.h>
4
5int main()
6{
7    pid_t pid1 = getpid();
8    printf("原pid为%d\n", pid1);
9
10    pid_t id = fork();
11
12    while(1)
13    {
14        if(id == -1)
15        {
16            perror("fork faild!");
17            break;
18        }
19        else
20        {
21            if(id == 0)
22            {
23                printf("这是子进程,pid:%d\n", getpid());
24            }
25            else
26            {
27                printf("这是父进程,pid:%d\n", getpid());
28            }
29        }
30
31        sleep(1);
32    }
33
34    return 0;
35}

运行结果:

可以看到确实是这样的,那么这样fork就衍生出三个问题:

fork三问题

1.为什么给子进程返回的是0,给父进程返回的是子进程的id?

2.为什么fork作为一个函数能返回两个值?

3.为什么id仅仅一个变量,能接收两个值?

对于问题1:在更为复杂的系统工程项目中,有时需要创建多个子进程,为了方便对个子进程进行管理,因此父进程需要得到创建的子进程的id;而每个子进程只会有一个父亲,因此只需要一个0。

对于问题2:函数在进行返回时,基本功能已经完成。对应fork函数,在return之前子进程已经创建,因此return实际返回的不是两个值,而是在两个进程中个返回的一个值。

对于问题3:主要涉及虚拟内存部分的写时拷贝,更深入内容在后续讲解。


【Linux】进程初阶(1)——基本进程理解》 是转载文章,点击查看原文


相关推荐


Bash 的 cd 命令
hubenchang05152025/11/6

#Bash 的 cd 命令 cd [-L|-P] [DIRECTORY] 功能 切换工作目录。 类型 Bash 内置命令。 参数 OPTION 选项: -L - 逻辑路径;在跟踪符号链接之前解析 ..(默认) -P - 物理路径;在跟踪符号链接之后解析 .. DIRECTORY - 要切换到的目录路径;省略表示切换到用户目录,- 表示切换到上次的工作目录 #示例 基本示例 $ pwd # 查看当前路径 /home/user/primer


规训 AI Agent 实践
清沫2025/11/1

AI 编程工具目前的发展可谓是三十年河东三十年河西,时不时就会有爆炸性的能力提升。初步使用,效果极其惊艳,随着使用的加深,就会发现 AI 会时不时犯蠢。本文总结 AI 协作的一些实践,希望帮助你让 AI 成为更可靠的编程伙伴。 别着急动手, 先制定计划 很多人使用 AI 编程工具时,习惯直接让 AI "帮我实现 xxx 功能",然后 AI 就立即开始写代码。这种方式在简单需求下可以工作,但面对复杂任务时容易出问题。等待十几分钟漫长的生码过程后,发现结果与预期相差甚远,既费时又费 token。 因


Nginx 高效动静分离:从原理到实战
银河技术2025/10/30

Nginx 高效动静分离:从原理到实战 Nginx 动静分离是 Web 性能优化中的经典策略,合理配置可显著提升网站性能、减轻应用服务器压力,并便于后续扩展与运维。本文将从 原理、配置、实战案例 以及 优化技巧 全面解析 Nginx 动静分离。 一、动静分离原理 1. 什么是动静分离? 动态资源(动):需要经过后台程序处理或数据库交互生成的内容,通常是非静态的。例如: /api/userinfo /search?keyword=abc *.jsp, *.php, *.do


前端基础:从0到1制作简单网页(三)
<但凡.2025/10/27

HTML容器元素分类 1. 通用容器 <div> - 通用块级容器 <span> - 通用内联容器(处理行内内容) 2. 语义化容器(HTML5新增) <header> - 页眉或章节头部 <footer> - 页脚或章节尾部 <main> - 文档主要内容 <section> - 文档章节 <article> - 独立内容块(如博客文章) <aside> - 侧边栏或相关内容 <nav> - 导航链接区域 <figure> -


从海量文档到精准数据:文档抽取技术驱动金融财税决策新范式
智能图像文字识别OCR2025/10/24

在金融与财税这个由海量文档驱动的领域中,效率与准确性是生命线。从繁复的财务报表、五花八门的发票,到冗长的合同与合规文件,传统的人工处理方式不仅成本高昂、效率低下,还极易出错。随着人工智能技术的成熟,文档抽取技术正成为解决这些痛点的关键利器,驱动着整个行业向智能化、自动化加速转型。 文档抽取技术简介及其工作原理 文档抽取技术是自然语言处理(NLP)和计算机视觉(CV)的一个交叉分支,其核心目标是从非结构化或半结构化的文档(如PDF、图片、扫描件)中,自动识别、定位并提取出特定的关键信息,并将其


金庸群侠传2攻略
funny-flash2025/10/22

金庸群侠传2攻略 金庸群侠传2加强版-免插件在线玩 本文为转载,原文地址:https://www.bilibili.com/opus/654149447904657428 一、前期衡阳城(游戏起始) 江湖称号:江湖小混混  (修炼《吐纳心法》至第5重时悟《吐纳术》)  1.田伯光欺负小尼姑任务。两次选帮助者,可提升一定属性。 2.客栈二楼,选1.上前搭讪(是否与他结拜影响到华山任务)  →选1 我虽非正人君子,但还知道廉耻!→得九转熊蛇丸  →选2 田兄在上,受小弟一拜!  →选1 阻止田伯光杀


每周读书与学习->JMeter主要元件详细介绍(一)配置元件
张永清-老清2025/10/21

每周读书与学习是由清华大学出版社出版的《JMeter核心技术、性能测试与性能分析》一书的作者推出,分享作者多年的IT从业经历,希望对很多计算机科学技术IT类专业毕业生以及IT从业者有所帮助。 在前面的学习中,我们已经讲到在Jmeter中配置元件主要用于完成性能测试中一些常见配置信息的配置,在前面的章节学习中,大家或许已经对配置元件的使用和作用有了一个初步的了解,在本章节学习中,我们将对一些常见的配置元件进行详细的介绍。 1、配置元件 1.1.CSV数据文件设置 如下图所示,CSV 数据文


AWS云基础设施可观测性完整指南
ivwdcwso2025/10/20

引言 在现代云原生架构中,可观测性已成为确保系统稳定性、性能和可靠性的关键要素。本文将深入探讨如何在AWS云环境中构建完整的可观测性体系,涵盖监控、日志、追踪和告警的最佳实践。 可观测性三大支柱 1. 指标监控 (Metrics) 指标是系统性能的数值化表示,提供系统健康状况的量化视图。 核心指标类型: 基础设施指标: CPU、内存、磁盘、网络 应用指标: 响应时间、吞吐量、错误率 业务指标: 用户活跃度、交易量、转化率 2. 日志记录 (Logs) 日志提供系


为何一个系统上线要经过N轮测试?带你看懂企业级发布体系
G探险者2025/10/19

大家好,我是G探险者! 在 IT 行业中,一个系统从开发完成到最终上线生产,并不是一蹴而就的过程。 你可能听说过这样的说法:“代码要经过 N 轮测试才能上线。” 从开发环境(DEV)到系统集成测试(SIT),再到用户验收测试(UAT),最后部署到生产环境(PROD),每一步都在为最终的稳定上线保驾护航。 这种多环境、多阶段的发布流程,表面上看似繁琐,但它背后承载的是风险控制、质量保障与团队协作的体系化思想。 如果缺乏这些环节,哪怕一个小小的配置错误、接口不兼容、性能瓶颈,都可能在生产环境引发严重


注入“侨动力” 锻造“湘非链”
hg01182025/10/17

2025年非洲侨团侨领侨商湖南行首场活动在长沙举办。 红网时刻新闻记者 聂伊岑 秦楼 卢欣 陈啸鼎 长沙报道 汇聚侨智侨力,深化湘非合作。 9月27日至30日,2025年非洲侨团侨领侨商湖南行活动在长沙、邵阳两地举办。 长沙市雨花区8个优质项目牵手非洲;15个湘非合作项目落地湖南湘江新区;邵阳海外订单纷至沓来;10位“海外招商大使”成为湖南与非洲之间最活跃的“经贸使者”。 本次湖南行成功将双方的深厚友谊与共同愿景转化为了实实在在的合作成果。 回顾4天的活动,不难发现,湖南与非洲的“朋

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0