【Linux】进程通信篇Ⅱ:共享内存、消息队列、信号量
文章目录
- 一、共享内存
- 1.1 一些接口
- 1. shmget 函数:申请一个 system v 的共享内存块
- 2. ftok 函数:设置唯一标识码
- 3. shmctl 函数:控制 system v 的共享内存块(可以删除、查看...)
- 4. shmat 函数:将进程与共享内存块 关联\ 挂接(attach)
- 5. shmdt 函数:将进程与共享内存块 去关联(detach)
- 1.2 一些命令
- 1. ipcs - - 查看三种 ipc 资源
- 2. ipcrm -- 删除某种 ipc 资源
- 1.3 结论
- 二、消息队列
- 1. msgget 函数:创建消息队列
- 2. msgctl 函数
- 3. msgsnd 和 msgrcv 函数,发送和接收消息
- 三、信号量
- 1. semget
- 2. semctl 函数:可以获取信号量的相关属性
- 3. semop 函数:对信号量进行操作
- 总结:
一、共享内存
我们知道,进程间通信的本质就是:让不同的进程,看到同一份资源
这里要介绍的同一份资源就是:内存块,即 共享内存(shared memory,简写为 shm)
- 共享内存的原理:
- 1.创建(key 和 共享内存)
- 2.关联进程 和 取消关联
- 3.释放共享内存
内存中的每块共享内存,会有一个 struct shm 结构体
,里面放着共享内存的全部属性,OS 通过这个结构体建立链表关系来对所有的共享内存进行管理,就等于把管理 shm 的问题转化成了管理链表的问题。
故:
共享内存
=
共享内存的内核数据结构 (伪代码:struct shm)
+
真正开辟的内存空间
1.1 一些接口
1. shmget 函数:申请一个 system v 的共享内存块
头文件:
#include <sys/ipc.h>
#include <sys/shm.h>// umask的头文件如下
#include <sys/types.h>
#include <sys/stat.h>
int shmget(key_t key, size_t size, int shmflg);
参数 key:
- 使用
ftok
函数设置的唯一标识码,他虽由用户设置,却是在内核中使用的
参数 size
- 需要申请共享内存块的大小,单位为字节,不足 PAGE 页(4KB)时,会向上对齐到 PAGE 页
参数 shmflg:
选项 IPC_CREAT and IPC_EXCL
单独使用 IPC_CREAT:创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就获取已经存在的共享内存并返回。
IPC_CREAT | IPC_EXCL :IPC_EXCL 必须要配合 IPC_CREAT 使用,创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就出错返回
意味着,一起使用时,如果创建成功,对应的shm,一定是最新的!IPC_CREAT | IPC_EXCL | 0666 :上面的基础上,添加权限(可以配合函数 umask(0) 使用)
返回值:
- 成功会返回一个共享内存标识符,失败返回 -1
2. ftok 函数:设置唯一标识码
头文件
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
参数 pathname
- 用户设置的路径
参数 proj_id
- 用户设置的项目 id
返回值:
- 根据用户传入的参数,结合一定的算法,返回一个冲突概率很低的值。ket_t 就是一个 32 位的整数,是对 int 的封装
3. shmctl 函数:控制 system v 的共享内存块(可以删除、查看…)
头文件
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数 shmid
- 需要的共享内存块的 shmid
参数 cmd:
- 选项 IPC_STAT:把用户传入 shmid 的相应内核数据结构信息复制到 buf 中(在调用者有读权限的情况下,才能成功)
- 选项 IPC_RMID:删除 shmid 为传入值的共享内存块
输出型参数 buf:
- 需要得到 ipc 信息时传一个相应类型的值用来接收结果
返回值:
- 失败返回 -1,成功则根据 cmd 传入的选项返回对应的值
//The buf argument is a pointer to a shmid_ds structure, defined in <sys/shm.h> as follows:struct shmid_ds {struct ipc_perm shm_perm; /* Ownership and permissions */size_t shm_segsz; /* Size of segment (bytes) */time_t shm_atime; /* Last attach time */time_t shm_dtime; /* Last detach time */time_t shm_ctime; /* Last change time */pid_t shm_cpid; /* PID of creator */pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */shmatt_t shm_nattch; /* No. of current attaches */...};//The ipc_perm structure is defined as follows (the highlighted fields are settable using IPC_SET):struct ipc_perm {key_t __key; /* Key supplied to shmget(2) */uid_t uid; /* Effective UID of owner */gid_t gid; /* Effective GID of owner */uid_t cuid; /* Effective UID of creator */gid_t cgid; /* Effective GID of creator */unsigned short mode; /* Permissions + SHM_DEST andSHM_LOCKED flags */unsigned short __seq; /* Sequence number */};
4. shmat 函数:将进程与共享内存块 关联\ 挂接(attach)
头文件
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
参数 shmid
- 需要的共享内存块的 shmid
参数 shmaddr:
- 用户可以选择虚拟地址作为共享内存块的起始地址
- 用户一般不定义,设为 nullptr 让 OS 自主定义即可
参数 shmflg:
- 选项 SHM_RDONLY:只读
- 0:可以读写
返回值:
- 挂接成功,返回共享内存块的虚拟地址的起始地址
5. shmdt 函数:将进程与共享内存块 去关联(detach)
头文件
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);
参数 shmaddr:
- 共享内存块的起始地址
返回值:
- 去关联成功返回 0,失败返回 -1
1.2 一些命令
1. ipcs - - 查看三种 ipc 资源
ipcs 就是进程间通信(ipc)资源
ipcs
:可以查看 消息队列、共享内存亏块、信号量
-m
:查看 共享内存块(memory)
-s
:查看 信号量(semaphore)
perms:权限
nattach:当前 ipc 挂接的进程数
2. ipcrm – 删除某种 ipc 资源
ipcrm
:删除一个 消息队列、共享内存亏块、信号量
-m
:删除一个共享内存块,后接 shmid
1.3 结论
-
两个进程管道通信一次,需要进行两次复制。而共享内存间的通信,可以让进程们直接在自己映射的地址空间中访问,减少了拷贝次数()
-
管道单方面关闭读写端会有相应的保护,而共享内存没有保护机制(同步互斥)。管道通过系统接口通信,共享内存直接通信
-
互斥:任何一个时刻,都只允许一个执行流在进行共享资源的访问,叫做加锁
-
我们把任何一个时刻,都只允许一个执行流在进行访问的共享资源,叫做 临界资源。凡是访问临界资源的代码,叫做临界区,控制进出临界区的手段造就了临界资源。
二、消息队列
1. msgget 函数:创建消息队列
头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg)
参数 key:
- 使用
ftok
函数设置的唯一标识码
参数 msgflg:
选项 IPC_CREAT and IPC_EXCL
单独使用 IPC_CREAT:创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就获取已经存在的共享内存并返回。
IPC_CREAT | IPC_EXCL :IPC_EXCL 必须要配合 IPC_CREAT 使用,创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就出错返回
意味着,一起使用时,如果创建成功,对应的shm,一定是最新的!IPC_CREAT | IPC_EXCL | 0666 :上面的基础上,添加权限(可以配合函数 umask(0) 使用)
返回值:
- 成功则返回消息队列的标识符
2. msgctl 函数
头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数 msqid
- 需要的消息队列的 msqid
参数 cmd:
- 选项 IPC_STAT:把用户传入 msqid 的相应内核数据结构信息复制到 buf 中(在调用者有读权限的情况下,才能成功)
- 选项 IPC_RMID:删除 msqid 为传入值的共享内存块
输出型参数 buf:
- 需要得到 ipc 信息时传一个相应类型的值用来接收结果
返回值:
- 成功返回 >= 0 的值,失败返回 -1
The msqid_ds data structure is defined in <sys/msg.h> as follows:struct msqid_ds {struct ipc_perm msg_perm; /* Ownership and permissions */time_t msg_stime; /* Time of last msgsnd(2) */time_t msg_rtime; /* Time of last msgrcv(2) */time_t msg_ctime; /* Time of last change */unsigned long __msg_cbytes; /* Current number of bytes inqueue (nonstandard) */msgqnum_t msg_qnum; /* Current number of messagesin queue */msglen_t msg_qbytes; /* Maximum number of bytesallowed in queue */pid_t msg_lspid; /* PID of last msgsnd(2) */pid_t msg_lrpid; /* PID of last msgrcv(2) */};The ipc_perm structure is defined as follows (the highlighted fields are settable using
IPC_SET):struct ipc_perm {key_t __key; /* Key supplied to msgget(2) */uid_t uid; /* Effective UID of owner */gid_t gid; /* Effective GID of owner */uid_t cuid; /* Effective UID of creator */gid_t cgid; /* Effective GID of creator */unsigned short mode; /* Permissions */unsigned short __seq; /* Sequence number */};
3. msgsnd 和 msgrcv 函数,发送和接收消息
头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数 msqid:
- 发送和接收访问的同一个消息队列
参数 msgp:
- 发送或接收的数据块
参数 msgsz:
- 发送或接收数据块的大小
参数 msgflg:
- 选项,一般填 0 即可
参数 msgtyp:
- msgbuf 里面的 mtype
// The msgp argument is a pointer to caller-defined structure of the following general form:struct msgbuf {long mtype; /* message type, must be > 0 */char mtext[1]; /* message data */
};
三、信号量
信号量 / 信号灯(semaphore),本质 就是一个计数器,是一个描述资源数量的计数器。
举个例子:
-
比如我们任何一个执行流,像访问临界资源中的一个子资源的时候,不能直接访问,需要 先申请信号量资源(P操作),此时 count-- 。只要申请信号量成功,未来就一定能拿到一个子资源。(类似摇号)
-
然后进入进程自己的临界区,访问对应的临界资源。
-
使用完成后,进程释放信号量资源(V操作),只要将计数器增加 count++,就表示将我们对应的资源进行了归还。
至此,进程通过执行代码来申请,意味着,所有进程都得先看到信号量,信号量就是一个共享资源。(信号量保护共享资源,自己却又是一个共享资源)
故,信号量必须保证自己的 ++ - - 是原子的
也,信号量被归类到了进程间通信
信号量部分未完待续~
1. semget
头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg);
参数 key:
- 使用
ftok
函数设置的唯一标识码,他虽由用户设置,却是在内核中使用的
参数 nsems:
- 申请信号量的个数(叫做信号量集)
参数 semflg:
选项 IPC_CREAT and IPC_EXCL
单独使用 IPC_CREAT:创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就获取已经存在的共享内存并返回。
IPC_CREAT | IPC_EXCL :IPC_EXCL 必须要配合 IPC_CREAT 使用,创建一个共享内存,如果共享内存不存在,就创建,如果已经存在就出错返回
意味着,一起使用时,如果创建成功,对应的shm,一定是最新的!IPC_CREAT | IPC_EXCL | 0666 :上面的基础上,添加权限(可以配合函数 umask(0) 使用)
返回值:
- 成功会返回一个信号量计数器标识符,失败返回 -1
2. semctl 函数:可以获取信号量的相关属性
头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);
参数 semid:
- 需要的信号量的semid
参数 semnum:
- 信号量编号
参数 cmd:
- 选项 IPC_STAT:把用户传入 msqid 的相应内核数据结构信息复制到 buf 中(在调用者有读权限的情况下,才能成功)
- 选项 IPC_RMID:删除 msqid 为传入值的共享内存块
返回值:
- 成功返回 >= 0 的值,失败返回 -1
//This function has three or four arguments, depending on cmd. When there are four, the
//fourth has the type union semun. The calling program must define this union as follows:union semun {int val; /* Value for SETVAL */struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */unsigned short *array; /* Array for GETALL, SETALL */struct seminfo *__buf; /* Buffer for IPC_INFO(Linux-specific) */};//The semid_ds data structure is defined in <sys/sem.h> as follows:struct semid_ds {struct ipc_perm sem_perm; /* Ownership and permissions */time_t sem_otime; /* Last semop time */time_t sem_ctime; /* Last change time */unsigned long sem_nsems; /* No. of semaphores in set */};//The ipc_perm structure is defined as follows (the highlighted fields are settable usingIPC_SET):struct ipc_perm {key_t __key; /* Key supplied to semget(2) */uid_t uid; /* Effective UID of owner */gid_t gid; /* Effective GID of owner */uid_t cuid; /* Effective UID of creator */gid_t cgid; /* Effective GID of creator */unsigned short mode; /* Permissions */unsigned short __seq; /* Sequence number */};
3. semop 函数:对信号量进行操作
头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
参数 sops:
- 需要用户自己定义后传入,设置结构体内容,以此达到对信号量的 PV 操作等等
//Each semaphore in a System V semaphore set has the following associated values:unsigned short semval; /* semaphore value */unsigned short semzcnt; /* # waiting for zero */unsigned short semncnt; /* # waiting for increase */pid_t sempid; /* ID of process that did last op *///semop() performs operations on selected semaphores in the set indicated by semid.
//Each of the nsops elements in the array pointed to by sops specifies an operation to be performed on a single semaphore.
//The elements of this structure are of type struct sembuf, containing the following members:unsigned short sem_num; /* semaphore number */short sem_op; /* semaphore operation */short sem_flg; /* operation flags */
总结:
共享内存、消息队列、信号量 这三种 ipc 都有各自的内核数据结构体,而结构体的第一个成员都是 struct ipc_perm xx_perm
。
可以理解为 OS 将这三种 ipc 都放进了一个 struct ipc_perm* ipc_id_arr[]
指针数组中进行管理(这里只是做理解解释,实际上更复杂)。
OS 通过指针,可以找到每个结构体(同时也是每个结构的第一个成员,即 struct ipc_perm xx_perm),在其中找到 key 值就可以确定。
要访问里面的内容时,以共享内存举例
((struct shmid_ds*)ipc_id_arr[n])->other...
对指针进行强转,就可以访问到其中内容了,这也是一种多态。
相关文章:
【Linux】进程通信篇Ⅱ:共享内存、消息队列、信号量
文章目录 一、共享内存1.1 一些接口1. shmget 函数:申请一个 system v 的共享内存块2. ftok 函数:设置唯一标识码3. shmctl 函数:控制 system v 的共享内存块(可以删除、查看...)4. shmat 函数:将进程与共享…...
8.14 校招 内推 面经
绿泡泡: neituijunsir 交流裙,内推/实习/校招汇总表格 1、半导体芯片一周资讯 - 小米OPPO之后,星纪魅族调整芯片业务,今年应届生或被全部优化,英伟达2024推出比H100更快的芯片 半导体芯片一周资讯 - 小米OPPO之后&…...

阿里云服务器安装部署Docker使用教程
本文阿里云百科分享如何在云服务ECS实例上,部署并使用Docker。Docker是一款开源的应用容器引擎,具有可移植性、可扩展性、高安全性和可管理性等优势。开发者可将应用程序和依赖项打包到一个可移植的容器中,快速发布到Linux机器上并实现虚拟化…...

WebRTC | ICE详解
目录 一、Candidate种类与优先级 二、ICE策略 1. iceServers 2. iceTransportPolicy 三、P2P连接 1.Nat类型 (1)完全锥型NAT (2)IP限制锥型NAT (3)端口限制锥型NAT (4)对称…...

网络设备(防火墙、路由器、交换机)日志分析监控
外围网络设备(如防火墙、路由器、交换机等)是关键组件,因为它们控制进出公司网络的流量。因此,监视这些设备的活动有助于 IT 管理员解决操作问题,并保护网络免受攻击者的攻击。通过收集和分析这些设备的日志来监控这些…...

2023年国赛数学建模思路 - 复盘:人力资源安排的最优化模型
文章目录 0 赛题思路1 描述2 问题概括3 建模过程3.1 边界说明3.2 符号约定3.3 分析3.4 模型建立3.5 模型求解 4 模型评价与推广5 实现代码 建模资料 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 描述 …...

Compute shader SV 理解图
本图转子:【Computeshader】个人总结_蒋伟博的博客-CSDN博客...

生信豆芽菜-多种算法计算免疫浸润
网址:http://www.sxdyc.com/immuneInfiltration 一、使用方法 1、数据准备 一个全编码蛋白的表达谱基因,其中行为基因,列为样本 第一列为基因为行名,不能重复 2、选择计算的方法(这里提供了5种免疫计算的方法&#x…...

逆向破解学习-单机斗地主
试玩 破解思路 9000 是成功的代码 Hook代码 import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class HookComJuneGameDouDiZhu extends HookImpl{ Override p…...

matplotlib绘制位置-时序甘特图
文章目录 1 前言2 知识点2.1 matplotlib.pyplot.barh2.2 matplotlib.legend的handles参数 3 代码实现4 绘制效果5 总结参考 1 前言 这篇文章的目的是,总结记录一次使用matplotlib绘制时序甘特图的经历。之所以要绘制这个时序甘特图,是因为22年数模研赛C…...

数据库概述、部署MySQL服务、必备命令、密码管理、安装图形软件、SELECT语法 、筛选条件
Top NSD DBA DAY01 案例1:构建MySQL服务器案例2:密码管理案例3:安装图形软件案例4:筛选条件 1 案例1:构建MySQL服务器 1.1 问题 在IP地址192.168.88.50主机和192.168.88.51主机上部署mysql服务练习必备命令的使用 …...

概率论与数理统计:第四章:随机变量的数字特征
文章目录 Ch4. 随机变量的数字特征1. 数学期望E(X)(1)数学期望的概念1.离散型①一维离散型随机变量X的数学期望: E X EX EX②一维离散型随机变量的函数的期望: E [ g ( X ) ] E[g(X)] E[g(X)]③二维离散型随机变量的函数的期望: E [ g ( X , …...
解决饿了么ui的对话框缩放和移动
import Vue from "vue";// v-dialogDrag: 弹窗拖拽水平方向伸缩 /** 使用方法* 将以下代码复制到一个js文件中,然后在入口文件main.js中import引入即可;* 给elementUI的dialog上加上 v-dialogDrag 指令就可以实现弹窗的全屏和拉伸了。* 给…...
Linux 中复制文件并保持修改时间等属性
一、遇到的问题 Linux使用cp命令复制文件备份时,发现文件的修改时间变成当前时间了,想要保留备份文件原有的修改时间及其它文件属性。 二、实现 1、cp命令 在 Linux 中,你可以使用 cp 命令来复制文件,并通过 -p 或 --preserve…...

Hugging News #0814: Llama 2 学习资源大汇总
每一周,我们的同事都会向社区的成员们发布一些关于 Hugging Face 相关的更新,包括我们的产品和平台更新、社区活动、学习资源和内容更新、开源库和模型更新等,我们将其称之为「Hugging News」。本期 Hugging News 有哪些有趣的消息࿰…...
可视化绘图技巧100篇进阶篇(五)-阶梯线图(Step Chart)
目录 前言 图表类型特征 适用场景 图例 绘图工具及代码实现 ECharts SMARTBI...
GPT带我学-设计模式-命令模式
1 你知道设计模式的命令模式吗 是的,我知道设计模式中的命令模式。命令模式是一种行为型设计模式,它将请求封装成一个对象,从而允许使用不同的请求、队列或日志来参数化其他对象。命令模式还支持撤销操作,并且可以提供事务的实现…...

互联网发展历程:跨越远方,路由器的启示
互联网的蓬勃发展,一直在追求更广阔的连接,更遥远的距离。然而,在早期的网络中,人们面临着连接距离有限的问题。一项重要的技术应运而生,那就是“路由器”。 连接受限的问题:距离有限 早期的网络受限于直接…...

postman入门基础 —— 接口测试流程
一、编写接口测试计划 接口测试计划和功能测试计划目标一致,都是为了确认需求、确定测试环境、确定测试方法,为设计测试用例做准备,初步制定接口测试进度方案。一般来说,接口测试计划包括概述、测试资源、测试功能、测试重点、测试…...
springcloud+nacos实现灰度发布
灰度发布 gateway网关实现灰度路由 灰度发布实体 package com.scm.boss.common.bean;import lombok.Data; import lombok.experimental.Accessors;import java.io.Serializable;/*** 灰度发布实体*/ Data Accessors(chain true) public class GrayBean implements Serializ…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...