进程(Process)

发布时间:2026/8/26 14:16:30

进程(Process)
一、概念进程是操作系统资源分配的最小单元文本段、数据段、系统数据段进程就是程序执行的过程包括创建、调度和消亡是活的程序一段数据的集合是死的二、常用命令ps -aux查看操作系统所有进程的相关参数PID进程ID号、创建者、状态、CPU占有率、内存占有率ps -aux | grep a.out ------------筛选出a.out的进程| 管道将前面的输出作为后面的输入grep 字符串查找ps -ef查看操作系统所有进程的相关参数PID、PPID父进程创建新进程的进程是该新进程的父进程子进程创建出来的新进程是子进程PID : Process ID 进程ID号PPID父进程ID号top动态查看进程状态及CPU占有率、内存占有率pstree查看进程间的创建关系族谱图pstree -sp 进程ID查看指定ID的进程的创建关系killkill -信号名称/信号ID PID给PID对应的进程发送一个信号kill -l 查看系统定义出来的信号kill -9 PID 结束一个进程S : 处于可中断睡眠状态的前台进程S: 处于可中断睡眠状态的后台进程T: 处于暂停态的后台进程fgfg 后台进程编号将后台进程调到前台jobs 查看当前后台进程编号三、进程的创建1、进程的内存空间电脑会在硬件层为每个进程准备真实的内存空间在32位操作系统有32根地址线中会为运行过程中的进程开辟0 - 4G虚拟内存空间在64位操作系统有64根地址线中会为运行过程中的进程开辟0 - 8G虚拟内存空间文本段存储代码和指令数据段存储全局变量、静态变量、字符串常量未经初始化变量值为0值在编译时分配空间程序运行时将a.out数据段加载到内存数据段中程序结束回收数据段空间系统数据段栈区操作系统管理区域、存放局部变量、执行到变量定义时分配空间超过变量 作用域回收变量空间未经初始化为随机值堆区程序员管理的区域malloc申请、free释放内核操作系统核心区域用户无法访问负责内存管理、CPU管理、硬件设备管理、进程管理、文件系统管理2、多个进程的存储1. 进程的空间是独立的2. 单核一个CPU在同一时刻只能执行一个任务3. 宏观并行微观串行4. 物理地址空间是独立的虚拟地址空间共用同一份所以多个进程并不是虚拟机地址空间相加四、进程的调度1、宏观并行围观串行多个进程在执行时总的看上去似乎是一起执行的但实际是因为电脑依次处理每个进程时的速度较快导致的该现象例如父子两个进程并不是同时执行的是有先后顺序的谁先谁后不清楚PCBProcess Control Block进程控制块操作系统内核管理进程的核心工具它为进程的创建、执行、切换和终止提供了必要的信息和控制机制MMUMemory Management Unit内存管理单元计算机硬件中的一个重要组件主要负责管理内存访问和虚拟内存与物理内存之间的地址转换2、进程的状态3、CPU调度任务规则一个任务执行完毕后如何选择下一个执行的任务常见进程调度算法a. 先来先执行后来后执行b. 高优先级调度算法c. 时间片轮转调度算法时间片CPU在某个进程任务中执行的一段时间d. 多级队列反馈e. 负载均衡调度算法4、进程相关的函数接口1forkman 2 forkpid_t fork(void);功能创建一个子进程参数缺省返回值成功在父进程中返回创建的子进程的PID在子进程中返回0失败返回-1getpid获取当前进程自己的PID号getppid获取当前进程的父进程的PID号注意1、子进程是父进程的不完全副本会复制父进程的数据区、BSS区、堆区、栈区、参数和环境变量 例一、例二、例三除了以上外还会复制输入输出缓冲区例四。 子进程的代码块和父进程的一样但是执行时从fork()后开始执行。2、父进程结束就会变成孤儿进程孤儿进程会被1号进程init收养例二3.、进程共用3G到4G这1G的内核空间4、但各自进程0到3G用户空间互相独立不能互相通信。5、 进程间不能直接通信要通信需要借助内核空间IPC机制进程的创建图例例一 int mian(void) { pid_t pid; pid fork(); if (-1 pid) { ERR_MSG(fail to fork); return -1; } if (0 pid) //if里边的内容执行完毕子进程结束 { printf(子进程(PID:%d)执行!\n, getpid()); else if (pid 0) //else if里边的内容执行完毕父进程结束 { printf(父进程(PID:%d)执行!\n, getpid()); } printf(都会执行!\n); return 0 }过程结果例二创建一个父进程的2个子进程要求子进程中打印自己的PID及父进程的PID父进程中打印自己的PID及两个子进程的PID父进程先结束子进程成为孤儿进程pid_t pid; pid_t pid1; pid fork(); if (-1 pid) { ERR_MSG(fail to fork); return -1; } if (0 pid) { printf(子进程1 PID:%d PPID:%d\n, getpid(), getppid()); } else if (pid 0) { pid1 fork(); if (-1 pid1) { ERR_MSG(fail to fork); return -1; } if (0 pid1) { printf(子进程2 PID:%d PPID:%d\n, getpid(), getppid()); } else if (pid1 0) { printf(父进程 PID:%d 子进程PID:%d %d\n, getpid(), pid, pid1); } }子进程先结束父进程不结束pid_t pid; pid_t pid1; pid fork(); if (-1 pid) { ERR_MSG(fail to fork); return -1; } if (0 pid) { printf(子进程1 PID:%d PPID:%d\n, getpid(), getppid()); } else if (pid 0) { pid1 fork(); if (-1 pid1) { ERR_MSG(fail to fork); return -1; } if (0 pid1) { printf(子进程2 PID:%d PPID:%d\n, getpid(), getppid()); } else if (pid1 0) { printf(父进程 PID:%d 子进程PID:%d %d\n, getpid(), pid, pid1); } } while (1) { }例三/***********************公用虚拟地址硬盘中的真实地址不同***********************/ pid_t pid; int *p NULL; int num 100; p malloc(4); if (NULL p) { ERR_MSG(fail to malloc); return -1; } pid fork(); if (-1 pid) { ERR_MSG(fail to fork); return -1; } if (0 pid) { *p 100; num 200; printf(*p %d, p %pnum %d\n, *p, pnum); //num200因为进程的真实空间是独立的 } else if (pid 0) { sleep(5); printf(*p %d, p %pnum %d\n, *p, p); //打印出的地址与上步打印的相同因为公用一个虚拟空间num100因为进程的真实空间是独立的 // 此时打印的地址为虚拟地址 }例四pid_t pid; //printf 标准输出流stdout库函数 printf(hello world\n); //加\n后缓存区会刷新所以在父进程中会打印子进程中不会打印 printf(hello world); //不加\n缓存区不会刷新所以在父子进程会都打印 pid fork(); if (-1 pid) { ERR_MSG(fail to fork); return -1; } if (0 pid) { sleep(1); } else if (pid 0) { sleep(5); }2exitman 3 exitvoid exit(int status);功能刷新缓存区并让进程结束参数status程序退出时的状态码。通常0表示程序正常退出非0值表示程序异常退出返回值缺省man 2 _exitvoid _exit(int status);功能进程直接结束参数status:进程结束的状态返回值缺省#include stdio.h #include sys/types.h #include unistd.h #include stdlib.h int main(void) { pid_t pid fork(); printf(pid %d\n, pid); if (pid 0) { printf(This is father process, myid %d, son pid %d, num %d\n, getpid(), pid, num); sleep(1); exit(0); } else if (0 pid) { printf(This is son process, myid %d, father pid %d, num %d\n, getpid(), getppid(), num); sleep(1); exit(0); } else { perror(fork error); } return 0; }3exec函数族#include unistd.hextern char **environ;int execl(const char *path, const char *arg, ... /* (char *) NULL */);int execlp(const char *file, const char *arg, ... /* (char *) NULL */);int execle(const char *path, const char *arg, ... /*, (char *) NULL, char * const envp[] */);int execv(const char *path, char *const argv[]);int execvp(const char *file, char *const argv[]);int execvpe(const char *file, char *const argv[],char *const envp[]);功能利用该进程空间执行另一份代码执行完毕后不会再次返回该进程空间以以下字母结尾的函数的含义l:参数以列表形式传递v:参数以指针数组形式传递p:在系统环境变量中找到path在path对应的路径下找文件e:执行新代码时更新环境变量注意forkexec用来启动一个新的软件/系统应用l:参数以列表形式传递int execl(const char *path, const char *arg, ... /* (char *) NULL */);/*************mian.c文件中的代码***************/ int mian(int argc,const char* argv) { printf(exec上面! PID:%d\n, getpid()); /* (./hello, ./hello, NULL) 第一个参数是执行谁第二个参数是对执行对象的传参一般都是传自己的名字还可以有第三个或者更多的参数但必须以NULL结尾代表结束了 */ execl(./hello, ./hello, NULL); //开始执行名为hello的可知执行文件 ERR_MSG(fail to execl); printf(看到我就表示execl失败了\n); } /************hello.c文件中的代码**************/ int main(int argcc,char* argv) { printf(hello\n); //这里使用gcc hello.c -o hello,生成名为hello的可执行文件 }代码执行结果v:参数以指针数组形式传递int execv(const char *path, char *const argv[]);/*******************min.c文件********************/ int mian(int argc,const char* argv) { char *parg[5] { ./hello, world, thank, you, NULL, }; printf(exec上面! PID:%d\n, getpid()); // execl(./hello, ./hello, world, thank, you, NULL); execv(./hello, parg); //parg的展开形式就是上一行的样子 ERR_MSG(fail to execl); printf(看到我就表示execl失败了\n); } /*******************hello.c文件*****************/ { int i 0; printf(hello world! PID:%d\n, getpid()); for (i 0; i argc; i) { printf(argv[%d] %s\n, i, argv[i]); //打印来自mian.c文件中传过来的参数 } }代码执行结果p:在系统环境变量中找到path在path对应的路径下找文件int execlp(const char *file, const char *arg, ... /* (char *) NULL */);#include stdio.h #include public.h extern char **environ; int main(int argc, const char **argv) { int i 0; pid_t pid; printf(system上面!\n); #if 0 //打印环境变量 printf(\n); for (i 0; environ[i] ! NULL; i) { printf(%s\n, environ[i]); } printf(\n); #endif // system(ls -l); //不用在终端处输入ls -l就可实现ls -l指令 pid fork(); if (-1 pid) { ERR_MSG(fail to fork); return -1; } if (0 pid) { execlp(ls, ls, -l, NULL); //在系统环境变量中找到path在path对应的路径下找文件到ls文件以执行ls -l指令 } else if (pid 0) { wait(NULL); //等待子进程执行结束后 回收子进程空间 printf(system下面!\n); } return 0; }代码执行结果五、进程的消亡1、僵尸进程1. 什么是僵尸进程进程执行结束空间没有被回收就会成为僵尸进程2. 如何避免产生僵尸进程让父进程先结束子进程会成为孤儿进程被init进程收养子进程结束时init进程会自动回收子进程空间子进程结束父进程回收子进程空间使用wait或者waitpid回收子进程空间2、进程回收函数接口当一个进程结束时操作系统会回收其占用的所有资源如内存、文件描述符等。如果父进程先于子进程结束子进程会成为孤儿进程并被init进程PID 为 1接管最终由init进程回收其资源。如果子进程先于父进程结束父进程需要通过wait()或waitpid()系统调用来回收子进程的资源。如果父进程没有调用这些函数子进程会成为僵尸进程直到父进程结束。1waitman 2 waitpid_t wait(int *wstatus);功能子进程执行结束后回收一个进程空间父进程有多个子进程则一个wait会回收掉最先结束的那个子进程空间参数wstatus存放进程结束状态的空间的首地址即是把exit函数中参数status的值存放到首地址为wstatus的空间中返回值成功返回回收到的子进程的PID失败返回-1WIFEXITED(wstatus)子进程是否正常结束代码执行完毕或者使用exit函数结束进程返回0或1WEXITSTATUS(wstatus)子进程结束的状态该函数会得到exit函数中的参数statusWIFSIGNALED(wstatus)是否被信号杀死使用kill -9 PID号代表被9号信号杀死返回0或1WTERMSIG(wstatus)获得杀死进程信号的编号注意1.wait具有阻塞功能子进程不结束父进程会一直等待直到子进程结束父进程再用wait回收子进程空间2.wait只会回收一个子进程空间那个先结束就回收掉那个3.wait具有同步的功能即wait后边的代码要等到子进程结束之后才会执行#include stdio.h #include public.h int main(int argc, const char **argv) { pid_t pid; pid_t ret; int status; pid fork(); if (-1 pid) { ERR_MSG(fail to fork); return -1; } if (0 pid) { printf(子进程(PID:%d)开始执行\n, getpid()); sleep(10); exit(10); } else if (pid 0) { printf(父进程(PID:%d)开始执行\n, getpid()); ret wait(status); printf(回收到子进程(PID:%d)空间了\n, ret); if (WIFEXITED(status)) { printf(正常结束,值%d\n, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf(被 %d 号信号杀死\n, WTERMSIG(status)); } } return 0; }2waitpidman 2 waitpidpid_t waitpid(pid_t pid, int *wstatus, int options);功能回收某个指定的子进程空间参数pid要回收的进程空间的ID号-1 回收任意一个子进程空间wstatus存放子进程结束状态空间首地址options0 阻塞回收WNOHANG 非阻塞回收返回值成功返回回收到子进程的PID失败返回-1如果没有回收到子进程空间返回0#include stdio.h #include public.h int main(int argc, const char **argv) { pid_t pid; pid_t ret; int status; pid fork(); if (-1 pid) { ERR_MSG(fail to fork); return -1; } if (0 pid) { printf(子进程(PID:%d)开始执行\n, getpid()); sleep(10); exit(10); } else if (pid 0) { printf(父进程(PID:%d)开始执行\n, getpid()); // ret wait(status); while (1) { ret waitpid(pid, status, WNOHANG); if (0 ret) { printf(子进程还没结束!\n); sleep(1); } else if (ret 0) { printf(回收到子进程(PID:%d)空间了\n, ret); if (WIFEXITED(status)) { printf(正常结束,值%d\n, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf(被 %d 号信号杀死\n, WTERMSIG(status)); } break; } } } return 0; }

相关新闻

systemVerilog 复习第一天——sv的仿真时间调度机制、enum、string、logic、数组、clock blocking

systemVerilog 复习第一天——sv的仿真时间调度机制、enum、string、logic、数组、clock blocking

2026/8/26 14:16:30

文章目录sv的仿真时间调度机制Time literalformattimescaleEvents RegionsVerilog的赋值连续赋值过程赋值eventprocesstime-solt为什么要引入event region调度机制详解简要流程图表总结sv的一些语法特性自动推断长度支持string、real等logicstringarray定宽数组动态数组clock b…

家庭版 Windows 安装 Docker 没有 Hyper-V 问题

家庭版 Windows 安装 Docker 没有 Hyper-V 问题

2026/8/26 14:16:30

一、关联文章: 1、Docker Desktop 安装使用教程 2、安装 Windows Docker Desktop - WSL问题 3、打开 Windows Docker Desktop 出现 Docker Engine Stopped 问题 二、问题解析 安装Docker出现问题,如下: Installation failed:one pre-requ…

超级详细的 Ollama 搭建本地 DeepSeek大模型

超级详细的 Ollama 搭建本地 DeepSeek大模型

2026/8/26 14:16:30

一、Ollama 下载与安装 Ollama 是一个开源项目,专注于帮助用户本地化运行大型语言模型(LLMs)。它提供了一个简单易用的框架,让开发者和个人用户能够在自己的设备上部署和运行 LLMs,而无需依赖云服务或外部 API。这对于…

如何将TradingView策略迁移到alpha-rptr:完整迁移实战指南

如何将TradingView策略迁移到alpha-rptr:完整迁移实战指南

2026/8/26 15:26:33

如何将TradingView策略迁移到alpha-rptr:完整迁移实战指南 【免费下载链接】alpha-rptr A trading bot for automated algorithmic trading on Binance Futures, Bybit, BitMEX and FTX written in python. 项目地址: https://gitcode.com/gh_mirrors/al/alpha-rp…

BioJava蛋白质结构叠加:CE、FATCAT与TM-align三种算法完整指南

BioJava蛋白质结构叠加:CE、FATCAT与TM-align三种算法完整指南

2026/8/26 15:26:33

BioJava蛋白质结构叠加:CE、FATCAT与TM-align三种算法完整指南 【免费下载链接】biojava :book::microscope::coffee: BioJava is an open-source project dedicated to providing a Java library for processing biological data. 项目地址: https://gitcode.com…

Jackett 部署教程:把上百个种子站装进一个搜索框

Jackett 部署教程:把上百个种子站装进一个搜索框

2026/8/26 15:26:33

Jackett 部署教程:把上百个种子站装进一个搜索框 【免费下载链接】Jackett API Support for your favorite torrent trackers 项目地址: https://gitcode.com/GitHub_Trending/ja/Jackett Jackett 是一个开源的种子搜索代理:它把上百个公共、半私…

元宝    LeetCode 3.无重复字符的最长子串  Python3实现

元宝 LeetCode 3.无重复字符的最长子串 Python3实现

2026/8/26 15:26:33

这是 LeetCode 3:无重复字符的最长子串 的 Python3 实现,使用滑动窗口(双指针),时间复杂度 O(n),是最推荐的解法。 ✅ 思路(滑动窗口) 用两个指针 left 和 right 维护一个窗口 用一…

数据分析其实没那么难:吃透这8张图,搞定90%的分析问题

数据分析其实没那么难:吃透这8张图,搞定90%的分析问题

2026/8/26 15:26:33

做数据分析久了,我越来越觉得,很多人不是不会分析,而是一开始就把这件事想复杂了。一提到数据分析,就容易联想到统计模型、算法、SQL、Python,好像工具越多,分析能力就越强。但真正到了企业里,大…

RuoYi-flowable 高频问题速查:流程部署失败、中文乱码、字体不显示等10个坑一次解决

RuoYi-flowable 高频问题速查:流程部署失败、中文乱码、字体不显示等10个坑一次解决

2026/8/26 15:16:32

RuoYi-flowable 高频问题速查:流程部署失败、中文乱码、字体不显示等10个坑一次解决 【免费下载链接】RuoYi-flowable 基RuoYi-vue flowable 6.7.2 的工作流管理 右上角点个 star 🌟 持续关注更新哟 项目地址: https://gitcode.com/gh_mirrors/ru/Ru…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/26 1:50:39

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/26 1:49:16

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/24 21:16:09

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

Python random 模块常用函数详解:从入门到实战

Python random 模块常用函数详解:从入门到实战

2026/8/26 0:05:45

目录 1. 引言2. 准备工作3. 基础随机函数4. 序列相关函数5. 随机种子与复现6. 实战案例7. 注意事项8. 常见问题与排查9. 总结 1. 引言 摘要: 本文系统介绍 Python 标准库 random 模块中最常用的随机数生成函数。内容涵盖基础随机函数(random()、unifor…

Hermes接入团队协作后,我推翻了三个效率假设

Hermes接入团队协作后,我推翻了三个效率假设

2026/8/26 0:05:45

聊《Hermes真能提效吗?先看流程里最慢的那一步》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要团队把 Hermes 接进项目三个月后,交付速度没有提升反而慢了。复盘后发现,最先…

免费AI大模型调教指南:打造专属网文写作助手

免费AI大模型调教指南:打造专属网文写作助手

2026/8/26 0:05:45

1. 先搞清楚“AI小说扩展模式”到底能帮你做什么如果你是一个刚开始写网文、或者卡在L3级别以下的作者,最头疼的可能是情节推进不下去、人物对话干瘪,或者世界观设定不够丰满。自己对着空白文档硬憋,效率很低。这时候,一个能理解你…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/22 2:02:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/22 4:13:47

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/22 1:32:34

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…