进程间通信之系统V共享内存

今天讲一讲进程间通信的另一种方式:系统V共享内存。

系统V共享内存是指:把所有共享数据放在共享内存区域,任何想访问该数据的进程都必须在本进程的地址空间新增一块内存区域,用来映射存放共享数据的物理内存页面,系统V通过映射特殊文件系统shm中的文件实现进程间共享内存通信的,即每个共享内存区域对应特殊文件系统shm中的一个文件。

系统V共享内存原理:

进程间需要共享的数据被放在一个叫作IPC共享内存区域中,所有需要访问该共享区域的进程都要把该共享区域映射到本进程的地址空间去。系统V共享内存通过shmget获得或创建一个IPC共享内存区域,并返回相应的标识符。内核在保证shmget获得或创建一个共享内存区,初始化该共享内存区相应的shmid_kernel结构的同时,还将在特殊文件系统shm中,创建并打开一个同名文件,并在内存中建立起该文件相应的dentry及inode结构,新打开的文件不属于任何一个进程,即任何进出都可以访问该共享内存区。

每一个共享内存区对象都对应特殊文件系统shm中的一个文件。一般来说,特殊文件系统shm中的文件是不能使用read()和write()等方法进行访问的,当采取共享内存的方法后,把其中的文件映射到进程地址空间后,可以直接采用访问内存的方式与其访问。

在建立一个共享内存区域后,还要将它映射到进程地址空间,系统可以通过调用shmat()完成此任务。因为在调用shmget()时,已经创建了文件系统shm中的一个同名文件与共享内存区域相对应,于是,调用shmat()的过程就相当于映射系统shm中的同名文件的过程。

系统V共享内存API

1、shmget函数

   功能:创建共享内存

   头文件:#include <sys/ipc.h>

   #include <sys/shm.h>

   原型:int shmget(key_t key,int size,int shmflg)

   说明:key为标识共享内存的键值:0或IPC_PRIVATE,当key的取值为IPC_PRIVATE时,则函数shmget()将创建一块新的共享内存;若key的取值为0时,而且参数shmflg中又设置了IPC_PRIVATE这个标志,则同样会创建一块新的共享内存

   返回值:成功,返回共享内存标识符;失败,返回-1。

注:用来获得共享内存区域的ID,如果不存在指定的共享内存区域就创建相应的区域。

2、shmat函数

   功能:映射共享内存

   头文件:#incldue <sys/ipc.h>

   #include <sys/shm.h>

   原型:void *shmat(int shmid,void * shmaddr,int flag)

   说明:shmid:shmget函数返回的共享存储标识符;

 flag:决定以什么方式来确定映射的地址,通常为0

   返回值:成功,返回共享内存映射到进程中的地址;失败,返回-1。

3、shmdt函数

   功能:解除进程对共享内存区域的映射

   头文件:#include <sys/types.h>

   #include <sys/ipc.h>

   #include <sys/shm.h>

   原型:int shmdt(const void * shmaddr)

   说明:shmaddr是要解除的映射进程的地址

   返回值:成功,返回0;出错,返回-1。

4、shmctl函数

   功能:对共享内存区域的控制操作

   头文件:#include <sys/types.h>

   #include <sys/ipc.h>

   #include <sys/shm.h>

   原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf)

   说明:shmid,共享内存标识符

 cmd,IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中

      IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享        内存的shmid_ds结构内

      IPC_RMID:删除这片共享内存内

 buf,共享内存管理结构体

   返回值:成功,返回0;出错:-1,错误原因存于error中。

共享内存允许两个或多个进程共享一给定的存储区,因为数据不需要来回复制,所以是最快的一种进程间通信机制。

示例:

shm1.c:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "shm_com.h"

int main(void)
{ 
    int running = 1;
    void *shared_memory = NULL;
    struct shared_use_st *shared_stuff;
    int shmid;

    /*创建共享内存*/
    shmid = shmget((key_t)1234,sizeof(struct shared_use_st),0666 | IPC_CREAT);
    if(-1 == shmid)
    {
        fprintf(stderr,"shmget failed!\n");
        exit(EXIT_FAILURE);
    }

    /*映射共享内存*/
    shared_memory = shmat(shmid,NULL,0);
    if(NULL == shared_memory)
    {
        fprintf(stderr,"shmat failed!\n");
        exit(EXIT_FAILURE);
    }
    printf("Memory attached at %X\n",(int)shared_memory);

    /*让结构体指针指向这块共享内存*/
    shared_stuff = (struct shared_use_st *)shared_memory;

    /*控制读写顺序*/
    shared_stuff->written_by_you = 0;

    /*循环的从共享内存中读数据,直到读到“end”为止*/
    while(running)
    {
        if(shared_stuff->written_by_you)
        {
            printf("You wrote:%s",shared_stuff->some_text);
            sleep(1);                  //读后再写
            shared_stuff->written_by_you = 0;
            if(0 == strncmp(shared_stuff->some_text,"end",3))
            {
                running = 0;
            }
        }
    }

    /*删除共享内存*/
    if(-1 == shmdt(shared_memory))
    {
        fprintf(stderr,"shmdt failed!!\n");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

shm2.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
#include "shm_com.h"

int main(void)
{
    int running = 1;
    void *shared_memory = NULL;
    struct shared_use_st *shared_stuff;
    char buffer[BUFSIZ];
    int shmid;

    /*创建共享内存*/
    shmid = shmget((key_t)1234,sizeof(struct shared_use_st),0600 | IPC_CREAT);
    if(-1 == shmid)
    {
        fprintf(stderr,"shmid failed!\n");
        exit(EXIT_FAILURE);
    }

    /*映射共享内存*/
    shared_memory = shmat(shmid,NULL,0);
    if(NULL == shared_memory)
    {
        fprintf(stderr,"shmat failed!\n");
        exit(EXIT_FAILURE);
    }
    printf("Memory attached at %X\n",(int)shared_memory);

    /*让结构体指针指向这块内存*/
    shared_stuff = (struct shared_use_st *)shared_memory;
   
   /*循环的向共享内存中写数据,直到写入的为“end”为止*/
   while(running)
   {
       while(1 == shared_stuff->written_by_you)
       {
           sleep(1);
           printf("waiting for client...\n");
       }
       printf("Enter some text:\n");
       fgets(buffer,BUFSIZ,stdin);
       strncpy(shared_stuff->some_text,buffer,TEXT_SZ);
       shared_stuff->written_by_you = 1;
       if(0 == strncmp(buffer,"end",3))
       {
           running = 0;
       }
   }

   /*删除共享内存*/
   if(-1 == shmdt(shared_memory))
   {
       fprintf(stderr,"shmat failed!\n");
       exit(EXIT_FAILURE);
   }
   exit(EXIT_SUCCESS);

}

调试结果:

./shm1

Memory attached at B7FFF000
You wrote:she
You wrote:ada
You wrote:end

./shm2

Memory attached at B7FB1000
Enter some text:
she
waiting for client...
awaiting for client...
Enter some text:
da
waiting for client...
waiting for client...
Enter some text:
end


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值