做电商网站哪里好,vps如何创建网站,下载学校网站模板下载,html简单网页成品目录
共享内存
共享内存相关函数
ftok 函数 -- 获取 key 值
什么是 key#xff1f; 如何生成 key #xff1f;
参数#xff1a;
返回值#xff1a;
封装#xff1a;
shmget 函数 -- 获取 shmid 值
什么是 shmid#xff1f;
shmid 和 key 的区别#xff1f;
…目录
共享内存
共享内存相关函数
ftok 函数 -- 获取 key 值
什么是 key 如何生成 key
参数
返回值
封装
shmget 函数 -- 获取 shmid 值
什么是 shmid
shmid 和 key 的区别
如何获取 shmid
参数
返回值
封装
shmctl 函数 -- 控制共享内存
参数
返回值
封装
删除共享内存
获得共享内存的状态
shmat 函数 -- 将共享内存挂接到进程地址空间
参数
返回值
封装
shmdt 函数 -- 取消挂接
参数
返回值
封装 共享内存 共享内存是一种在计算机系统中允许多个进程访问同一块内存区域的机制。它是进程间通信IPC, Inter-Process Communication的一种方式可以让不同的进程通过读写同一个内存段来交换数据。这种方式非常高效因为它避免了数据复制的过程直接在内存中进行数据的传递。 在操作系统层面当一个进程创建了一个共享内存区后其他被授权的进程可以映射这个共享内存到自己的地址空间并且可以像访问普通内存一样访问这块共享内存。这种机制对于需要频繁交换大量数据的应用程序特别有用比如数据库管理系统、多媒体应用程序等。 共享内存相关函数
ftok 函数 -- 获取 key 值
什么是 key
因为两个进程访问同一块共享内存而且操作系统不止一块共享内存怎么保证两个或者不同的进程看到的是同一块共享内存呢操作系统如何管理所有的共享内存 我们给共享内存提供内核中的唯一性的标识称为 key 主要用于在创建或访问共享内存段时标识这个内存段。 如何生成 key
#include sys/ipc.hkey_t ftok(const char *pathname, int proj_id);
参数 pathname指向一个字符串的指针该字符串包含了一个路径名。这个路径名可以是任何文件或目录的路径甚至可以是一个不存在的文件路径。其主要目的是为了生成一个唯一的键值。 proj_id一个整数用于进一步区分不同的共享内存段或信号量集。proj_id通常是一个较小的整数因为 ftok函数返回的 key 值是由路径名和 proj_id组合计算得出的。过大的 proj_id可能会影响到 key 值的分布。 这个值通常由程序员根据应用程序的需要自行选择。通常情况下开发者会根据项目的实际需求来选择一个合适的 proj_id。例如可以使用一个固定的数字或者是某种有意义的编码只要保证它是唯一且一致的即可。 返回值 如果成功ftok函数返回一个非负的键值key_t类型。如果失败返回 -1并且会设置 errno来表明错误的原因。 封装
key_t GetShmKeyOrDie(const char* pathname,const int pro_jid)
{key_t kftok(pathname,pro_jid);//得到key值if(k0)//获取失败{cerr ftok failed,errno:errno, errstring:strerror(errno)endl;exit(1);//直接终止程序}return k;//获取成功
}
shmget 函数 -- 获取 shmid 值
什么是 shmid shmid是一个整数用于标识一个已创建的共享内存段。一旦获取了shmid进程就可以通过它来进一步操作共享内存段如附着、分离等。类似于文件描述符。 shmid 和 key 的区别 key用于标识共享内存段的逻辑键值而shmid则是操作系统分配给这个共享内存段的一个内部标识符用来管理具体共享内存段。两者共同作用于共享内存机制确保多个进程能够正确地共享同一块内存。key是一个逻辑上的标识符用于创建或查找共享内存段而shmid是一个物理上的标识符用于具体的操作共享内存段。key是静态的一旦生成就不会改变而shmid是动态的每次创建共享内存段时操作系统都会返回一个新的shmid。key用于解决“找到”共享内存的问题而shmid用于解决“操作”共享内存的问题。 如何获取 shmid
#include sys/shm.hint shmget(key_t key, size_t size, int shmflg);
参数 key用于标识共享内存段的键值。这个键值通常通过 ftok函数生成。 size共享内存段的大小以字节为单位。如果key对应的一个共享内存段已经存在那么这个参数将被忽略。在内核中共享内存的大小以 4KB 为基本单位且你只能用你申请的大小为了避免空间浪费建议 size 的大小是 n*4KB。 shmflg一组标志位用于控制创建和访问共享内存段的行为。 常见的标志位包括 IPC_CREAT如果指定的 key对应的共享内存段不存在则创建一个新的共享内存段如果存在则直接获取该共享内存。传该参数得到的共享内存不一定是新的可能是之前创建的。IPC_EXCL独自使用时没有意义。IPC_EXCL|IPC_CREATkey对应的共享内存段如果不存在就会创建一个新的共享内存如果已经存在则shmget会失败并返回 EEXIST错误。传该参数得到的共享内存一定是新的权限位如0666用于设置共享内存段的访问权限。 返回值 如果成功shmget返回一个非负整数即 shmid。如果失败返回 -1并且设置 errno以指示失败的原因。 封装
int CreateShmOrDie(key_t key, int size, int flag)
{//得到共享内存的shmidint shmidshmget(key,size,flag);if(shmid0)//创建失败{cerr shmget failed, errno:errno, errstring:strerror(errno)endl;exit(2);}return shmid;//创建成功
}int CreateShm(key_t key,int size)
{//创建一个新的共享内存并设置权限return CreateShmOrDie(key,size,IPC_CREAT|IPC_EXCL|0666);
}int GetShm(key_t key,int size)
{return CreateShmOrDie(key,size,IPC_CREAT);
}
shmctl 函数 -- 控制共享内存
#include sys/shm.hint shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数 shmid共享内存段的标识符通常通过shmget函数获得。 cmd命令代码用于指定要执行的操作。 cmd参数的常用值 IPC_STAT获取共享内存段的状态信息并存储在buf指向的结构体中。IPC_RMID删除共享内存段。 buf指向struct shmid_ds类型的指针struct shmid_ds包含有关共享内存段的各种信息包括权限、所有者等。若不需要该参数可以传 NULL 。 返回值 如果shmctl函数成功执行它返回 0。如果shmctl函数执行失败它返回 -1并且会设置 errno 以指示失败的原因。 封装
删除共享内存
void DeleteShm(int shmid)
{int nshmctl(shmid,IPC_RMID,nullptr);if(n0)cerr Delete failed,errno:errno, errstring:strerror(errno)endl;elsecout Delete success, shmid:shmidendl;
}
获得共享内存的状态
string ToHex(key_t k)//将 key 值转为十六进制
{char buffer[1024];//用C语言方便用 %x 直接转为十六进制snprintf(buffer,sizeof(buffer),0x%x,k);return buffer;
}void DebugShm(int shmid)
{struct shmid_ds shmds;int n shmctl(shmid, IPC_STAT, shmds);if (n 0)cerr shmctl failed endl;else{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;//对应的key}
}
shmat 函数 -- 将共享内存挂接到进程地址空间
上面的 shmget 函数只是创建了一个共享内存但是这个共享内存并没有映射到进程的地址空间还不属于进程所以需要调用函数把该共享内存挂接到进程地址空间中。
#include sys/shm.hvoid *shmat(int shmid, const void *shmaddr, int shmflg);
参数 shmid共享内存段的标识符通常通过shmget函数获得。 shmaddr指定共享内存段在进程地址空间中的起始地址。如果设置为 NULL则由系统选择一个合适的地址。 shmflg一组标志位用于控制共享内存段的映射行为。 常用的标志位包括 SHM_RDONLY只读方式映射共享内存段。SHM_RND映射地址将是 4K 对齐的随机地址。SHM_REMAP如果共享内存段已经存在于进程地址空间中则重新映射共享内存段。 当 shmflg设为 0 时意味着不使用任何特定的标志位默认按照系统默认的方式进行映射。具体来说 默认映射方式系统会选择一个适合的地址来映射共享内存段。读写模式默认情况下映射是以读写模式进行的而不是只读模式。无特殊要求不强制使用特定的映射地址也不要求重新映射已经存在的共享内存段。 返回值 如果成功shmat返回一个指向共享内存段的指针。如果失败返回(void *)-1并且会设置 errno以指示失败的原因。 void*空指针类型是C语言中的一种指针类型表示一个未指定类型的指针。void* 可以存储任何类型的指针值并且在使用时需要显式转换为目标类型的指针。 封装
void *ShmAttach(int shmid)
{void* addrshmat(shmid,nullptr,0);if((long long int)addr-1){//挂接失败cerr attach failed,errno:errno, errstring:strerror(errno)endl;return nullptr;}else{//挂接成功return addr;}
}
shmdt 函数 -- 分离
shmdtshared memory detach函数用于将先前通过shmat函数映射到进程地址空间的共享内存段分离detach出来。分离后共享内存段仍然存在于系统中只是不再映射到当前进程的地址空间中。这意味着进程不能再直接访问这块共享内存中的数据。
#include sys/shm.hint shmdt(const void *shmaddr);
参数 shmaddr指向先前通过shmat函数映射到进程地址空间的共享内存段的指针。 返回值 如果 shmdt函数成功执行它返回 0。如果 shmdt函数执行失败它返回 -1并设置 errno以指示失败的原因。 封装
void ShmDetach(void *addr)
{int nshmdt(addr);if(n0){cerr Detach failed,errno:errno, errstring:strerror(errno)endl;}
}