linux IPC---共享内存

共享内存

共享内存是允许两个或多个进程共享同一块内存区域,因为进程可以直接读写内存,不需要任何数据的拷贝,这是一种最快的进程间通信方式。共享内存是多进程之间的通信方法 ,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。当然,多个进程同时访问共享区就得需要一些同步机制,如信号量或互斥锁等,这些以后再记录,本文先讲最简单的共享内存使用方式。

linux共享内存操作的四个函数

shmget函数:创建一个共享内存对象并返回共享内存标识符。
shmat函数:把创建的共享内存映射到具体的进程空间去,映射后就可以在本进程使用这块地址。
shmctl函数:共享内存管理,完成对共享内存的控制。
shmdt函数:撤销映射共享内存,但是并不删除所指定的共享内存区,而只是将先前用shmat函数连接好的共享内存脱离目前的进程。

shmget 函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key,int size,int shmflg)

返回值:若成功,返回共享内存段标识符;若出错,返回-1
参数说明:

  • Key:IPC_PRIVATE (为0,比较常见的一种)
  • Size:共享内存区大小
  • Shmflg:同 open 函数的权限位,也可以用八进制表示法

shmat函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
char *shmat(int shmid,const void *shmaddr,int shmflg)

返回值:若成功,返回被映射的段地址;若出错,返回-1
参数说明:

  • shmid:要映射的共享内存区标识符
  • shmaddr:将共享内存映射到指定位置(若为 0 则表示把该段共享内存映射到调用进程的地址空间)
  • Shmflg
    - SHM_RDONLY:共享内存只读
    - 默认 0:共享内存可读写

shmctl函数

#include <sys/types.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf)

返回值:若成功,返回0;若出错,返回-1
参数含义:

  • shmid:共享内存标识符
  • cmd:

    • IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中
    • IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内
    • IPC_RMID:删除这片共享内存
  • buf:共享内存管理shmid_ds结构体。

以下是 shmid_ds 结构:

struct shmid_ds  
{  
    struct ipc_perm shm_perm;   /* operation permission struct */  
    size_t          shm_segsz;  /* size of segment in bytes */  
    pid_t           shm_lpid;   /* pid of last shmop() operation */  
    pid_t           shm_cpid;   /* pid of creator */  
    shmatt_t        shm_nattch; /* number of current attaches */  
    time_t          shm_atime;  /* last-attach time */  
    time_t          shm_dtime;  /* last-detach time */  
    time_t          shm_ctime;  /* last-change time */  
}; 

shmdt函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr)

返回值:若成功,返回0;若出错,返回-1
参数说明:

  • Shmaddr:被映射的共享内存段地址

示例程序

/* share_memory.c*/

#include <unistd.h>  
#include <stdio.h>  
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

#include <sys/shm.h>
#define BUFF 1024
int main ()   
{   
    int shmid;
    pid_t pid; 
    char *shmaddr;//共享内存地址
    /*创建共享内存*/
    if((shmid=shmget(IPC_PRIVATE,BUFF,0666))<0)
    {
        perror("shmget");
        exit(-1);
    }
    else
        printf("Create shared memory,id = %d\n",shmid);

    if ((pid = fork()) < 0)
    {
        perror("fork");
        exit(-1);
    }
    else if (pid == 0) //子进程
    {
        /*映射共享内存*/
        if((shmaddr=shmat(shmid,0,0))<(char *)0)
        {
            perror("shmat");
            exit(-1);
        }
        else
            printf("I am child,shmat shared memory success\n"); 
        //子进程往共享内存写数据
        strcpy( shmaddr, "from child process\n");
        //snprintf(shmaddr, 13, "%012d", 12345);
        //本函数调用并不删除所指定的共享内存区,而只是将先前用shmat函数连接(attach)好的共享内存脱离(detach)目前的进程
        shmdt(shmaddr);
        return 0;
    }
    else //父进程
    {
        //保证子进程已经往共享内存写入数据了
        sleep(2);
        /*映射共享内存*/
        if((shmaddr=shmat(shmid,0,0))<(char *)0)
        {
            perror("shmat");
            exit(-1);
        }
        else
            printf("I am parent,shmat shared memory success\n");
        //读取共享内存的数据
        printf("read from share memory: %s",shmaddr);
        shmdt(shmaddr);
        //等待子进程退出
        waitpid(pid,NULL,0);
        exit(0);
    }
    return 0;  
}

实验结果:

ubuntu:~/test/process_test$ ./share_memory
Create shared memory,id = 0
I am child,shmat shared memory success
I am parent,shmat shared memory success
read from share memory: from child process

以上程序,我们调用shmget函数创建共享内存区,然后调用fork函数创建子进程,在子进程中调用shmat映射共享内存地址,然后往共享内存区写数据。在父进程中,同样调用shmat函数映射共享内存区,然后从共享内存区读取子进程写入的数据。

共享内存的简单应用就说到这了,下次讲消息队列。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值