有关函数

  1. shmget  创建一个共享内存对象并返回共享内存标识符或得到一个共享内存标识符

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

    返回值:失败返回-1,成功返回标识

    参 数: key:一般由系统调用fotk获得,为0(IPC_PRIVATE)时会建立新共享内存对象

         size:要创建或得到的共享内存对象的大小,以字节为单位,和页(4k)对齐

         shmflg :

             0      取共享内存标识符,若不存在则函数会报错

             IPC_CREAT    如果内核中不存在键值与key相等的共享内存,则新建一个共享内                     存;如果存在这样的共享内存,返回此共享内存的标识符

             IPC_CREAT|IPC_EXCL   如果内核中不存在键值与key相等的共享内存,则新建                           一个消息队列;如果存在这样的共享内存则报错  

    =========================================================================


  2. shmat  连接共享内存标识符为shmid的共享内存,链接成功后把共享内存区地址映射到进程地        址空间,随后该进程可以像访问本地空间一样来访问这块内存


    原型:void *shmat(int shmid,const void *shmaddr,int shmflg);

    返回值:失败返回-1,成功返回shmid所标识的共享内存的映射到虚拟地址空间的地址

    参 数:shmid:共享内存的标识

        shmaddr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL时内核自己决定一          个合适的地址位置

        shmflg:

           SHM_RDONLY:只读模式

           其它:读写模式

    =========================================================================

  3. shmdt  与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存

    原型:int shmdt(const void*shmaddr);

    返回值:失败返回-1,成功返回0

    参数:shmaddr:shmat()的返回值(共享内存区地址映射到进程的地址)

    =========================================================================

  4. shmctl  对共享内存的管理与控制

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

    返回值:失败返回-1,成功返回0

    参数:shmid:共享内存的标识

        cmd:

          IPC_RMID:删除这片共享内存

          IPC_STAT:得到共享内存的状态,并复制到第三个参数buf所指向的结构体中

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

        buf:共享内存管理结构体

     

      struct shmid_ds {

           struct ipc_perm shm_perm;    /* Ownership and permissions */

           size_t     shm_segsz;   /* Size of segment (bytes) */

           time_t     shm_atime;   /* Last attach time */

            time_t     shm_dtime;   /* Last detach time */

            time_t     shm_ctime;   /* Last change time */

            pid_t      shm_cpid;    /* PID of creator */

            pid_t      shm_lpid;    /* PID of last shmat(2)/shmdt(2) */

            shmatt_t    shm_nattch;  /* No. of current attaches */                       ...

     };

  =========================================================================


代码实现:

shm.h

#ifndef _SHM_H_
#define _SHM_H_

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

#define __PATH__ "."
#define __PROJ_ID__ 0x26
#define SIZE 4096

int creat_shm(int _size);
int get_shm(int _size);
int destory_shm(int _shm_id);

#endif

shm.c

#include"shm.h"

static int comm_shm(int _size,int flags)
{
    key_t _key=-1;
    if((_key=ftok(__PATH__,__PROJ_ID__))<0){
        perror("ftok");
        return -1;
    }
    int _shm_id=-1;
    if((_shm_id=shmget(_key,_size,flags))<0){
        perror("shmget");
        return -1;
    }
    return _shm_id;
}

int creat_shm(int _size)
{
    return comm_shm(_size,IPC_CREAT|IPC_EXCL|0666);
}
int get_shm(int _size)
{
    return comm_shm(_size,IPC_CREAT);
}

int destory_shm(int _shm_id)
{
    if(shmctl(_shm_id,IPC_RMID,NULL)<0){
        perror("shmctl");
        return -1;
    }
    return 0;
}

shm_server.c

#include"shm.h"

int main()
{
    int _shm_id=creat_shm(SIZE);
    char *addr=(char*)shmat(_shm_id,0,0);
    sleep(5);
    int j=0;
    while(1){
        while(j<128){
            printf("%c  ",addr[j++]);
        }
        printf("\n");
        break;
    }   
    sleep(8);
    if(shmdt(addr)<0){
        perror("attach is failed!\n");
    }
    printf("attach has success!\n");

    sleep(3);
    destory_shm(_shm_id);
    printf("destory successed\n");

    return 0;
}


shm_client.c

#include"shm.h"

int main()
{
    int _shm_id=get_shm(SIZE);
    sleep(2);
    char *addr=(char*)shmat(_shm_id,0,0);

    int i=0;
    while(i<128){
        addr[i++]=i;
    }   
    sleep(10);
    if(shmdt(addr)<0){
        perror("attach is failed!\n");
    }   
    printf("attach has success!\n");
    return 0;
}


Makefile

.PHONY:all
all:shm_server shm_client
shm_server:shm_server.c shm.c 
    gcc -o $@ $^
shm_client:shm_client.c shm.c
    gcc -o $@ $^

.PHONY:clean
clean:
    rm -rf shm_server shm_client


运行server端结果:

wKiom1cQ34Cxq36cAABFR52II9o777.png

运行client端结果:

wKiom1cQ3nayD0XLAAAPJESjvFw624.png


运行前系统中所有的共享内存段(因为我们只关注它的变化,因此后面的截图只截了一部分)

wKioL1cQ3y6RwjtuAAA6QO20Pso193.png

运行中:  可以看到系统中多了shmid为1048590的Shared Memory,它的nattch为1



wKioL1cQ3zDRBwklAAAMzGjRlXk082.png

                   shmid为1048590的Shared Memory,它的nattch增加为2

wKioL1cQ3zCAmCVdAAAM-QcLmWk327.png

                  shmid为1048590的Shared Memory,它的nattch减少为1

wKiom1cQ3nfRN0GoAAAOQ3lUhU8687.png

                  shmid为1048590的Shared Memory,它的nattch减少为0

wKiom1cQ3nejtMMJAAANMcgBkPA826.png

                  shmid为1048590的Shared Memory,不存在了

wKioL1cQ3zGxOyQFAAAKEvhD8qI696.png