Linux中如何共享内存

75次阅读
没有评论

共计 4738 个字符,预计需要花费 12 分钟才能阅读完成。

这篇文章给大家分享的是有关 Linux 中如何共享内存的内容。丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考,一起跟随丸趣 TV 小编过来看看吧。

1 共享内存的概念及使用过程

1) 共享内存的概念

共享内存是 IPC 机制中的一种。

共享内存:即允许两个或多个进程共享一个给定的存储区。

2) 共享内存的使用过程

① 进程 1 创建共享内存,接着映射共享内存。

② 进程 2 获取共享内存,映射共享内存。

③ 交互完成,进程 1 分离共享内存,进程 2 分离共享内存。

④ 进程 1 删除共享内存。

2 共享内存相关的结构及函数

0) 共享内存相关的结构

内核为每个共享存储段维护着一个结构,该结构至少要为每个共享存储段包含以下成员。

struct shmid_ds { struct ipc_perm shm_perm; //  操作权限  size_t shm_segsz; //  段的大小(以字节为单位) time_t shm_atime; //  上一个进程附加到该段的时间  time_t shm_dtime; //  上一个进程分离开该段的时间  time_t shm_ctime; //  上一个进程修改该段的时间  pid_t shm_cpid; //  创建该段进程的 PID pid_t shm_lpid; //  上个 shmat(2)/shmdt(2) 的 PID shmatt_t shm_nattch; //  当前附加到该段的进程的个数  ... };

系统为每一个 IPC 对象保存一个 ipc_perm 结构体,该结构说明了 IPC 对象的权限和所有者,每一个版本的内核各有不用的 ipc_perm 结构成员。

struct ipc_perm { key_t __key; //  为  shmget(2)  调用提供的键值  uid_t uid; //  共享内存所有者的有效用户 UID gid_t gid; //  共享内存所有者所属组的有效组 GID uid_t cuid; //  共享内存创建者的有效用户 UID gid_t cgid; //  共享内存创建者所属组的有效组 ID unsigned short mode; //  特权  + SHM_DEST  和 SHM_LOCKED  标志  unsigned short __seq; //  序列号  };

1)shmget 函数

shmget 函数用于创建或者获取共享内存,并返回其描述符 id。

① 函数原型。

int shmget(key_t key,size_t sizie,int shmflg)

② 头文件。

include  sys/ipc.h  include  sys/shm.h

③ 参数。

key: 共享内存的键值。

size: 共享内存的大小。

shmflg: 打开标志,如果使用了 IPC_CREAT,则会新创建一块共享内存。

④ 返回值。

成功:返回创建或者获取到的共享内存的描述符。

失败:-1。

2)shmat 函数

shmat 函数用于映射共享内存,即将进程连接到它的地址空间。

① 函数原型。

void *shmat(int shmid,const void *shmaddr,int shmflg)

② 头文件。

include  sys/types.h  include  sys/shm.h

③ 参数。

shmid: 要映射的共享内存的描述符。

shmaddr: 共享内存的地址。

shmflg: 打开标志,如果使用了 IPC_CREAT, 则会新创建一块共享内存。

④ 返回值。

成功:返回创建或者获取到的共享内存的描述符。

失败:-1。

3)shmdt 函数

shmdt 函数用于分离共享内存,即操作完存储段后,用此函数可以将进程与此存储段脱离开,即断掉与共享内存的联系。

① 函数原型。

int shmdt(const void *shmaddr)

② 头文件。

#include  sys/types.h  #include  sys/shm.h

③ 参数。

shmaddr: 要断开的共享内存的映射地址。

④ 返回值。

成功:0。

失败:-1。

4)shmctl 函数

shmctl 函数用于控制共享内存,通过参数可以对共享内存进行特定的操作。

① 函数原型。

int shmctl(int shmid, int cmd, struct shmid_ds *buf)

② 头文件。

#include  sys/ipc.h  #include  sys/shm.h

③ 参数。

shmid: 要控制的共享内存的 id。

cmd: 决定执行什么样的控制操作,如 IPC_RMID(表示删除)。

buf: 获取 linux 中描述共享内存的 shmid_ds 结构。基本不使用。

cmd 可去的参数如下,需要参照上面的结构 shmid_ds 和 ipc_perm:

IPC_STAT:取此段的 shmid_ds 结构,并将它存储在由 buf 指向的结构中。

IPC_SET:按 buf 指向的结构中的值设置与此共享存储段相关的 shmid_ds 结构中的下列 3 个字段:shmperm.uid、shm  perm.gid 和 shmperm.mode。

此命令只能由下列两种进程执行:一种是其有效用户 ID 等于 shm_perm.cuid 或 shmperm.uid 的进程; 另一种是具有超级用户特权的进程。

IPC_RMID:从系统中删除该共享存储段。

除非使用该段的最后一个进程终止或与该段分离,否则不会实际上删除该存储段。

不管此段是否仍在使用,该段标识符都会被立即删除,所以不能再用 shmat 与该段连接。

此命令只能由下列两种进程执行:一种是其有效用户 ID 等于 shm_perm.cuid 或 shm_perm.uid 的进程; 另一种是具有超级用户特权的进程。

下面两个命令只能由超级用户执行:

SHM_LOCK:在内存中对共享存储段加锁。

SHM_UNLOCK:解锁共享存储段。

④ 返回值。

成功:根据不同的操作返回不同的值。

失败:-1。

3 实例代码

下面用两个进程,给大家演示下共享内存的使用过程。

实例代码如下,说明都在代码注释中了。

WriteMemory.c。

#include  sys/types.h  #include  sys/shm.h #include  sys/ipc.h  #include  stdio.h  #include  unistd.h  #include  stdlib.h  #include  string.h  #define SIZE 1024 //  可输入 1K 字符串  struct SharedMemoryST { int ReadWriteFlag; //  表明是谁放进去的  char CharData[SIZE]; //  字符数组保存用户输入数据  }; int main(int argc,char *argv[]) { int shmid; int ReadStatusFlag = 1; //  内存中数据是否被读走,1 未被读走  struct SharedMemoryST *shm; //  共享内存结构变量  char buffer[SIZE]; key_t key=ftok(/tmp ,12); //  创建共享内存的键值,如果提示创建失败(一般是没有 quit 引起的),可以修改读写进程的键值,都要改成同一数字  //1  创建共享内存  shmid = shmget(key,sizeof(struct SharedMemoryST),IPC_CREAT|IPC_EXCL|0777); if(shmid == -1) //  如果创建失败  { printf( \nCreating share memory fail!\n\n  exit(1); } //2  映射共享内存  shm = shmat(shmid,NULL,0); //  内存 id,映射的位置,映射的标志(此无特殊要求) //3  查询写入的  while(ReadStatusFlag) //  循环检查写入共享内存的数据是否被读走,读走后退出循环  { while(shm- ReadWriteFlag == 1) { sleep(1); printf(\nWaiting read memory!\n  } //  获取用户输入  printf(\nPlease input data or input  quit  to exit!\n\n  fgets(buffer,SIZE,stdin); //  参数:字符串的位置,长度,获取的方式位置  //  将用户输入的字符串放入共享内存  strncpy(shm- CharData,buffer,SIZE);//  参数:目的数据,源数据,数据大小  shm- ReadWriteFlag = 1; if(strncmp(buffer, quit ,4) == 0) //  最后一个参数为比较字符的数量  { ReadStatusFlag = 0; //  写入共享内存的数据已经被读走  } } //4  脱离共享存  shmdt((const void *)shm); return 0; }

ReadMemory.c。

#include  sys/types.h  #include  sys/shm.h #include  sys/ipc.h  #include  stdio.h  #include  unistd.h  #include  stdlib.h  #define SIZE 1024 //  可输入 1K 字符串  struct SharedMemoryST { int ReadWriteFlag; //  标明是读进程还是写进程放入了数据  char CharData[SIZE]; //  保存用户输入数据  }; int main(int argc,char *argv[]) { int shmid; int ReadStatusFlag = 1; //  内存中数据是否被读走的标志位,1 表示未被读走  struct SharedMemoryST *shm; //  共享内存结构  key_t key=ftok( /tmp ,12); //  创建共享内存的键值,如果提示创建失败,修改一下数字即可, 读写进程都要改成同一数字  //1  创建 / 获取共享内存  shmid = shmget(key,sizeof(struct SharedMemoryST),IPC_CREAT|0777);// 分配大小为结构大小,1234 是随便给的键值  //2  映射共享内存  shm = (struct SharedMemoryST *)shmat(shmid,NULL,0); // 内存 id,映射的位置,映射的标志(此无特殊要求) shm- ReadWriteFlag = 0; //3  检查是否收到信息,收到 quit 退出  while(ReadStatusFlag) { // 打印共享内存  if(shm- ReadWriteFlag == 1) //  等于说明有相应的数据  { printf( \nThe write context is: %s\n ,shm- CharData); shm- ReadWriteFlag = 0; if(strncmp(shm- CharData, quit ,3) == 0) { ReadStatusFlag = 0; //  结束查询,退出  } } } //4  脱离共享内存  shmdt((const void *)shm); //5  删除共享内存  shmctl(shmid,IPC_RMID,0); }

写共享内存先创建共享内存, 写入数据,读共享内存读取数据,通过标志查询方式,退出输入 quit。

运行结果如下:

感谢各位的阅读!关于“Linux 中如何共享内存”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-25发表,共计4738字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)