linux IPC---共享内存

来源:互联网 发布:高性能网络编程1 编辑:程序博客网 时间:2024/06/05 23:44

共享内存

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

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 1024int 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_memoryCreate shared memory,id = 0I am child,shmat shared memory successI am parent,shmat shared memory successread from share memory: from child process

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

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

原创粉丝点击