秒懂Linux之共享内存

fe594ea5bf754ddbb223a54d8fb1e7bc.gif

目录

共享内存概念

模拟实现共享内存

创建key阶段

​编辑创建共享内存阶段

删除共享内存阶段 

查看共享内存属性阶段

挂接共享内存到进程阶段

取消共享内存与进程挂接阶段

进程通信阶段

添加管道改进版

共享内存函数

shmget函数

shmat函数

shmdt函数

shmctl函数


共享内存概念

共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。

之前所学的管道通信本质上是通过内核的文件作为媒介进行通信的,而共享内存则是脱离创建管道的范畴转而到物理内存中让两进程通信~

然而共享内存可以存在很多个,因为不仅仅只有进程A,B需要利用共享内存通信,其他进程之间也需要,所以OS必须管理所有的共享内存~如何管理呢?——先描述,再组织~

那么核心问题来了,如何让不同进程之间看到同一份共享内存呢?前的管道通信是通过创建管道这种特殊文件让不同进程在内核中通过打开同一个文件来建立通信~而在共享内存中进程之间应该如何做到呢?总不能共享内存被创建起那进程A,B就自然而然可以通信了吧?

如果key由OS生成,它哪里知道我们的心思,是无法保证让指定进程看到同一份共享内存的这样倒不如我们自己给一个参数(ftok)来让进程A,B作为同一个参数形成key,这样就可以看到同一份内存了~

模拟实现共享内存

创建key阶段

//设置好生成key的两个参数
const char* pathname = "/home/LJZ";
const int proj_id = 0x66;//转16进制
std::string ToHex(key_t k)
{char buffer[1024];//将k以16进制的格式写入buffersnprintf(buffer,sizeof(buffer),"%x",k);return buffer;
}//获取key函数
key_t GetShmKey()
{//生成keykey_t k = ftok(pathname,proj_id);if (k < 0){std::cerr << "ftok error, errno : " << errno << ", error string: " << strerror(errno) << std::endl;exit(1);}return k;
}
#include "Comm.hpp"int main()
{key_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;return 0;
}

 成功让客户端与服务端都拿到了我们自定义生成的key~



创建共享内存阶段

//创建共享内存函数
int CreatShm(key_t key,int size,int flag)
{//shmget创建共享内存的返回值类似我们创建文件的文件描述符fdint shmid = shmget(key,size,flag);if (shmid < 0){std::cerr << "shmget error, errno : " << errno << ", error string: " << strerror(errno) << std::endl;exit(2);}return shmid;
}//为服务端使用,由服务端来创建共享内存
int SSCreateShm(key_t key, int size)
{// IPC_CREAT: 不存在就创建,存在就获取// IPC_EXCL: 没有意义// IPC_CREAT | IPC_EXCL: 不存在就创建,存在就出错返回return CreatShm(key, size, IPC_CREAT | IPC_EXCL | 0666);
}//为客户端使用,在共享内存存在的情况下获取它
int SCGetShm(key_t key, int size)
{return CreatShm(key, size, IPC_CREAT);
}
int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//获取共享内存int shmid = SCGetShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;return 0;
}
int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//创建共享内存int shmid = SSCreateShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;return 0;
}

以上说明在进程结束时如果我们没有主动释放掉共享内存它会一直存在~

ps:ipcrm -m shmid :手动删除共享内存 

删除共享内存阶段 


//删除共享内存函数
void DeleteShm(int shmid)
{//删除共享内存int n = shmctl(shmid,IPC_RMID,nullptr);if (n < 0){std::cerr << "shmctl error" << std::endl;}else{std::cout << "shmctl delete shm success, shmid: " << shmid << std::endl;}
}

int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//创建共享内存int shmid = SSCreateShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;sleep(10);//10s后删除共享内存DeleteShm(shmid);return 0;
}

查看共享内存属性阶段

//查看共享内存属性函数
void ShmDebug(int shmid)
{//shmid_ds里面存储着其信息struct shmid_ds shmds;//将与标识符为 shmid 的共享内存段相关联的内核数据结构中的信息复制到由 buf 所指向的 shmid_ds 结构中int n = shmctl(shmid, IPC_STAT, &shmds);if (n < 0){std::cerr << "shmctl error" << std::endl;return;}std::cout << "shmds.shm_segsz: " << shmds.shm_segsz << std::endl;std::cout << "shmds.shm_nattch:" << shmds.shm_nattch << std::endl;std::cout << "shmds.shm_ctime:" << shmds.shm_ctime << std::endl;std::cout << "shmds.shm_perm.__key:" << ToHex(shmds.shm_perm.__key) << std::endl;
}

int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//创建共享内存int shmid = SSCreateShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;//查看共享内存信息ShmDebug(shmid);sleep(10);//10s后删除共享内存DeleteShm(shmid);return 0;
}

以上只是为了演示shmctl中模式的多样化选择~

挂接共享内存到进程阶段


//挂接共享内心到进程函数
void *ShmAttach(int shmid)
{//挂接进程,成功则返回已连接的共享内存段的地址。void *addr = shmat(shmid, nullptr, 0);if ((long long int)addr == -1){std::cerr << "shmat error" << std::endl;return nullptr;}return addr;
}

int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//获取共享内存int shmid = SCGetShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;sleep(2);//挂接共享内存到客户端char * addr = (char*)ShmAttach(shmid);std::cout << "Attach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;sleep(5);return 0;
}
int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//创建共享内存int shmid = SSCreateShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;//挂接共享内存到服务端char * addr = (char*)ShmAttach(shmid);std::cout << "Attach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;sleep(10);//查看共享内存信息//ShmDebug(shmid);sleep(100);//10s后删除共享内存DeleteShm(shmid);return 0;
}

有时候我们不想让某一个进程挂接共享内存了,总不能直接把共享内存删掉吧?可以取消它与共享内存的挂接~

取消共享内存与进程挂接阶段

//取消共享内存与进程挂接函数
void ShmDetach(void *addr)
{//通过进程的虚拟地址取消挂接int n = shmdt(addr);if (n < 0){std::cerr << "shmdt error" << std::endl;}
}
int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//获取共享内存int shmid = SCGetShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;sleep(2);//挂接共享内存到客户端char * addr = (char*)ShmAttach(shmid);std::cout << "Attach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;sleep(5);//客户端取消挂接ShmDetach(addr);std::cout << "Detach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;return 0;
}

int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//创建共享内存int shmid = SSCreateShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;//挂接共享内存到服务端char * addr = (char*)ShmAttach(shmid);std::cout << "Attach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;sleep(10);//查看共享内存信息//ShmDebug(shmid);//服务端取消挂接ShmDetach(addr);std::cout << "Detach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;sleep(20);//10s后删除共享内存DeleteShm(shmid);return 0;
}

所有工作准备完毕,进入通信阶段~


进程通信阶段

int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//创建共享内存int shmid = SSCreateShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;//挂接共享内存到服务端char * addr = (char*)ShmAttach(shmid);std::cout << "Attach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;sleep(10);//查看共享内存信息//ShmDebug(shmid);std::cout << "Detach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;//通信阶段,服务端读取数据//直接打印在共享内存中的数据for(;;){cout << "shm content: " << addr << std::endl;sleep(1);}sleep(100);//服务端取消挂接ShmDetach(addr);sleep(20);//10s后删除共享内存DeleteShm(shmid);return 0;
}

int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//获取共享内存int shmid = SCGetShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;sleep(2);//挂接共享内存到客户端char * addr = (char*)ShmAttach(shmid);std::cout << "Attach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;sleep(5);//通信阶段,客户端写入数据//客户端直接在共享内存中写数据memset(addr,0,defaultsize);for (char c = 'A'; c <= 'Z'; c++) {addr[c - 'A'] = c;sleep(1);}sleep(100);//客户端取消挂接ShmDetach(addr);std::cout << "Detach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;sleep(5);return 0;
}

不过这种通信有个无法避免的缺陷:在默认情况中作为shm读取方是不会去阻塞等待写入方的,就一直读取不管有没有写入优点是共享内存这种方式是进程通信中速度最快的,因为写入数据的同时另外一方直接在内存中就可以读取,不需要管道传递的媒介但缺点也很明显,无法提供进程间协同的任何机制,如果我们想要发送一整段字符串时会被这种方式切割为一个个字符读入~

为了能控制想要发送与读取的大小,我们利用管道来实现同步的机制~

添加管道改进版


#define Mode 0666
#define Path "./fifo"//命名管道
class Fifo
{
public:Fifo(const string &path = Path) : _path(path){umask(0);int n = mkfifo(_path.c_str(), Mode);if (n == 0){cout << "mkfifo success" << endl;}else{cerr << "mkfifo failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;}}~Fifo(){int n = unlink(_path.c_str());if (n == 0){cout << "remove fifo file " << _path << " success" << endl;}else{cerr << "remove failed, errno: " << errno << ", errstring: " << strerror(errno) << endl;}}private:string _path; // 文件路径+文件名
};//利用管道进行同步数据
class Sync
{
public:Sync() : rfd(-1), wfd(-1){}//以读方式打开管道void OpenRead(){rfd = open(Path, O_RDONLY);if (rfd < 0)exit(1);}//以写方式打开管道void OpenWrite(){wfd = open(Path, O_WRONLY);if (wfd < 0)exit(1);}//让服务端等待管道中写端的写入,到达一定量后再一次性读取bool Wait(){bool ret = true;uint32_t c = 0;ssize_t n = read(rfd, &c, sizeof(uint32_t));//读取的数据大小为uint32_t时提示准备唤醒服务端读取数据代替之前时时刻刻读if (n == sizeof(uint32_t)){std::cout << "server wakeup, begin read shm..." << std::endl;}//代表管道写端关闭,读端读取数据结束,返回0else if (n == 0){ret = false;}else{return false;}return ret;}//往管道写入数据,量够的时候作提示唤醒服务端void Wakeup(){uint32_t c = 0;//往管道写入数据ssize_t n = write(wfd, &c, sizeof(c));//写够数据量的时候,提示唤醒服务端可以读取了assert(n == sizeof(uint32_t));std::cout << "wakeup server..." << std::endl;}~Sync() {}private:int rfd;int wfd;
};
#include "Comm.hpp"
#include <unistd.h>
#include "Fifo.hpp"
int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//获取共享内存int shmid = SCGetShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;sleep(2);//挂接共享内存到客户端char * addr = (char*)ShmAttach(shmid);std::cout << "Attach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;sleep(5);//通信阶段,客户端写入数据//客户端直接在共享内存中写数据memset(addr,0,defaultsize);Sync syn;//写方式打开管道syn.OpenWrite();for (char c = 'A'; c <= 'Z'; c++) {addr[c - 'A'] = c;sleep(1);//往管道写入数据,写够时发出提示:可唤醒服务端读取数据syn.Wakeup();}sleep(100);//客户端取消挂接ShmDetach(addr);std::cout << "Detach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;sleep(5);return 0;
}


int main()
{//获取keykey_t key = GetShmKey();std::cout << "key: " << ToHex(key) << std::endl;//创建共享内存int shmid = SSCreateShm(key,defaultsize);std::cout << "shmid: " << shmid << std::endl;//挂接共享内存到服务端char * addr = (char*)ShmAttach(shmid);std::cout << "Attach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;sleep(10);//查看共享内存信息//ShmDebug(shmid);// 0. 先引入管道Fifo fifo;Sync syn;//读方式打开管道syn.OpenRead();std::cout << "Detach shm success, addr: " << ToHex((uint64_t)addr) << std::endl;//通信阶段,服务端读取数据//直接打印在共享内存中的数据for(;;){//读取数据量不够的时候,退出,不让打印(读取)出内容//读取数据量够的时候,打印堆积的内容if(!syn.Wait()) break;cout << "shm content: " << addr << std::endl;sleep(1);}sleep(100);//服务端取消挂接ShmDetach(addr);sleep(20);//10s后删除共享内存DeleteShm(shmid);return 0;
}

管道意义就在于不要让服务端读那么快,而是在管道内积累一定数据量后再一次性读取数据,实现同步的机制。

共享内存函数

shmget函数

功能:用来创建共享内存
原型
int shmget(key_t key, size_t size, int shmflg);
参数
key: 这个共享内存段名字
size: 共享内存大小
shmflg: 由九个权限标志构成,它们的用法和创建文件时使用的 mode 模式标志是一样的
返回值:成功返回一个非负整数,即该共享内存段的标识码;失败返回-1

shmat函数

功能:将共享内存段连接到进程地址空间
原型
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数
shmid: 共享内存标识
shmaddr: 指定连接的地址
shmflg: 它的两个可能取值是 SHM_RND SHM_RDONLY
返回值:成功返回一个指针,指向共享内存第一个节;失败返回 -1
shmaddr NULL ,核心自动选择一个地址
shmaddr 不为 NULL shmflg SHM_RND 标记,则以 shmaddr 为连接地址。
shmaddr 不为 NULL shmflg 设置了 SHM_RND 标记,则连接的地址会自动向下调整为 SHMLBA 的整数倍。公式: shmaddr -
(shmaddr % SHMLBA)
shmflg=SHM_RDONLY ,表示连接操作用来只读共享内存

shmdt函数

功能:将共享内存段与当前进程脱离
原型
int shmdt(const void *shmaddr);
参数
shmaddr: shmat 所返回的指针
返回值:成功返回 0 ;失败返回 -1
注意:将共享内存段与当前进程脱离不等于删除共享内存段

shmctl函数

功能:用于控制共享内存
原型
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数
shmid: shmget 返回的共享内存标识码
cmd: 将要采取的动作(有三个可取值)
buf: 指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值:成功返回 0 ;失败返回 -1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/145501.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Redis中Hash(哈希)类型的基本操作

文章目录 一、 哈希简介二、常用命令hsethgethexistshdelhkeyshvalshgetallhmgethlenhsetnxhincrbyhincrbyfloathstrlen 三、命令小结四、哈希内部编码方式五、典型应用场景六、 字符串&#xff0c;序列化&#xff0c;哈希对比 一、 哈希简介 几乎所有的主流编程语言都提供了哈…

一文带你掌握 tmux -- 高效的终端复用工具

一、什么是tmux&#xff1f; tmux 是一款开源的终端复用器&#xff0c;允许用户在一个终端窗口中访问多个终端会话&#xff0c;同时提供了会话管理功能&#xff0c;使得用户可以在同一个窗口中创建、访问和控制多个会话。它对于需要同时运行多个命令行程序的用户来说非常有用&…

自动化立体仓库几种典型的解决方案

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》 完整版文件和更多学习资料&#xff0c;请球友到 知识星球【智能仓储物流技术研习社】 自行下载。 文件《自动化立体仓库几种典型的解决方案》的核…

浅谈“流量回放”

一、流量回放定义 “流量回放”通常指的是将之前记录的网络请求和响应数据重新发送到系统中&#xff0c;以模拟真实用户的操作。这种技术主要用于测试和调试目的&#xff0c;帮助开发人员和测试人员更好地理解系统在特定条件下的行为。 二、流量回放的技术原理&#xff1a; 数…

3、无线通信系统的组成

通常把实现信息传输的系统称为通信系统&#xff0c;下图表示一个通信系统的基本组成。在通信系统中&#xff0c;一般要进行两种变换与反变换。在发送端&#xff0c;第一个变换是输入变换器&#xff0c;它把要传输的信号变为电信号&#xff0c;该信号一般是低频的&#xff0c;而…

YOLOv5白皮书-第Y1周:调用官方权重进行检测

>- **&#x1f368; 本文为[&#x1f517;365天深度学习训练营](小团体&#xff5e;第八波) 中的学习记录博客** >- **&#x1f356; 原作者&#xff1a;[K同学啊](K同学啊-CSDN博客)** 一、前言 拖了好久&#xff0c;终于要开始目标检测系列了。自己想过好几次&#xf…

python中ocr图片文字识别样例(一)

一、使用easyocr安装依赖 pip install easyocr pip install opencv-python-headless # 处理图像二、具体实现&#xff0c;此处有个缺陷&#xff0c;大家可以尝试解决下&#xff0c;识别的文字打印结果没问题&#xff0c;但是图片识别出现乱码&#xff1a; 2.1 具体识别的图片…

创新驱动,技术引领:2025年广州见证汽车电子技术新高度

汽车行业的创新浪潮正汹涌澎湃&#xff0c;一场引领未来出行的科技盛宴即将拉开帷幕&#xff01; AUTO TECH 2025 第十二届广州国际汽车电子技术展览会将于 2025 年 11 月 20日至 22 日在广州保利世贸博览馆&#xff08;PWTC Expo&#xff09;隆重举行。 作为亚洲地区领先的汽…

AI助力低代码平台:从智能化到高效交付的全新变革

引言&#xff1a;技术融合的新时代 随着数字化转型的深入推进&#xff0c;企业对软件开发的需求迅速增长。然而&#xff0c;传统开发模式的高成本、长周期&#xff0c;以及对专业技术人才的依赖&#xff0c;正逐渐成为瓶颈。与此同时&#xff0c;低代码平台的崛起为企业提供了一…

传输大咖44 | 云计算企业大数据迁移如何更安全高效?

在云计算时代&#xff0c;数据已成为企业最宝贵的资产之一。对于依赖云服务的企业和组织来说&#xff0c;大数据迁移是实现业务扩展和优化的关键步骤。然而&#xff0c;这一过程并非没有挑战。传统的文件传输方式在安全性、稳定性和速度上往往无法满足云计算企业的需求。本文将…

Shire 智能体市场:IDE 一键安装多智能体,协同打造集体智慧 Copilot

太长不看版&#xff1a;在新版本&#xff08;0.8&#xff09;的 Shire 中&#xff0c;你可以通过 Shire 智能体市场&#xff0c;一键下载和安装多个智能体&#xff0c;并直接在你的当前项目中使用。与此同时&#xff0c;你还可以 将你的 Shire 代码段或者智能体上传到 Shire 智…

智慧火灾应急救援航拍检测数据集(无人机视角)

智慧火灾应急救援。 无人机&#xff0c;直升机等航拍视角下火灾应急救援检测数据集&#xff0c;数据分别标注了火&#xff0c;人&#xff0c;车辆这三个要素内容&#xff0c;29810张高清航拍影像&#xff0c;共31GB&#xff0c;适合森林防火&#xff0c;应急救援等方向的学术研…

GRU(门控循环单元)的原理与代码实现

1.GRU的原理 1.1重置门和更新门 1.2候选隐藏状态 1.3隐状态 2. GRU的代码实现 #导包 import torch from torch import nn import dltools#加载数据 batch_size, num_steps 32, 35 train_iter, vocab dltools.load_data_time_machine(batch_size, num_steps)#封装函数&…

免费在线压缩pdf 压缩pdf在线免费 推荐简单好用

压缩pdf在线免费&#xff1f;在日常生活和工作学习中&#xff0c;处理PDF文件是常见任务。但有时PDF文件体积较大&#xff0c;给传输、存储和分享带来不便。因此&#xff0c;学习PDF文件压缩技巧十分必要。压缩PDF文件是指通过技术手段减小文件占用的存储空间&#xff0c;同时尽…

【TabBar嵌套Navigation案例-JSON的简单使用 Objective-C语言】

一、JSON的简单使用 1.我们先来看一下示例程序里边,产品推荐页面, 在我们这个产品推荐页面里面, 它是一个CollectionViewController,注册的是一个xib的一个类型,xib显示这个cell,叫做item,然后,这个邮箱大师啊,包括这个图标,以及这些东西,都是从哪儿来的呢,都是从…

0x08 MotionEye 视频监控组件 list 信息泄漏洞 CVE-2022-25568

参考&#xff1a; MotionEye 视频监控组件 list 信息泄漏洞 CVE-2022-25568 | PeiQi文库 (wgpsec.org) 一、漏洞描述&#xff1a; motionEye是用Python写的motion的Web前端&#xff0c;它可以监视视频信号并检测运动。它可以与多种类型的摄像机配合使用,也可以与电影文件一起…

ElementUI 用span-method实现循环el-table组件的合并行功能

需要把指定列的相同数据合并起来&#xff08;项目中用的是updateTime&#xff09; 后端返回的数据格式&#xff1a; html&#xff1a; <el-tab-pane label"执行记录概览" name"fourth" v-loading"loading"><el-timeline v-if"re…

活动目录安全

活动目录安全 1.概述2.常见攻击方式SYSVOL与GPP漏洞MS14-068漏洞Kerberoast攻击内网横移抓取管理员凭证内网钓鱼与欺骗用户密码猜解获取AD数据库文件 3.权限维持手段krbtgt账号与黄金票据服务账号与白银票据利用DSRM账号利用SID History属性利用组策略利用AdminSDHolder利用SSP…

【Geoserver使用】REST API调用(工作空间部分)

文章目录 前言一、Geoserver REST API(GeoServer Workspace)二、GeoServer Workspace接口使用1.GET请求 /workspaces2.POST请求 /workspaces3.GET请求 /workspaces/{workspaceName}4.PUT /workspaces/{workspaceName}5.DELETE /workspaces/{workspaceName} 总结 前言 根据Geos…

操作系统笔记三

进程 把一个静态程序通过OS在内存中让cpu执行起来的动态执行过程叫进程 写代码都是用户态&#xff0c;而进程在执行过程中需要完成特定的功能&#xff0c;这些功能呢只有操作系统能提供&#xff0c;比如说读写文件&#xff0c;读写文件的过程是与硬盘打交道&#xff0c;这个过程…