Bootstrap

进程间通信方式-共享内存

目录

1.特点

2.使用步骤

3.函数接口

3.1创建key值

3.2创建或打开共享内存

3.3映射共享内存

3.4取消映射

3.5删除共享内存

4.命令

5.基本操作


1.特点

(1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。

(2)为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读写这一内存区而不需要进行数据的拷贝,从而大大提高的效率。

(3) 由于多个进程共享一段内存,因此也需要依靠某种同步机制,如互斥锁和信号量等

2.使用步骤

(1) 创建 key值

(2) 创建或打开共享内存

(3) 映射共享内存到用户空间

(4) 撤销映射

(5) 删除共享内存

3.函数接口

3.1创建key值

key_t ftok( constchar *pathname, int proj_id);

功能:创建出来的具有唯一映射关系的一个key值,帮助操作系统用来标识一块共享内存

参数:Pathname:已经存在的可访问文件的名字

                Proj_id:一个字符(因为只用低8位)

返回值:成功:key值

                失败:-1

// 将文件的索引节点号取出ls -i,前面加上proj_id得到key_t的返回值。如指定文件的索引节点号为65538,换算成16进制为 0x010002取后4位,而你指定的ID值为38,换算成16进制为0x26,则最后的key_t返回值为0x26010002。中间的01是系统编号。

3.2创建或打开共享内存

int shmget( key_t key, size_t size, int shmflg);

功能:创建或打开共享内存

参数:

        key 键值

        size 共享内存的大小

        shmflg IPC_CREAT | IPC_EXCL | 0777

返回值:成功 shmid

                出错 -1

//当IPC_CREAT | IPC_EXCL时, 如果没有该块共享内存,则创建,并返回共享内存ID。若已有该块共享内存,则返回-1。

3.3映射共享内存

void *shmat( int shmid, constvoid *shmaddr, int shmflg); //attaches

功能:映射共享内存,即把指定的共享内存映射到进程的地址空间用于访问

参数:

                shmid 共享内存的id号

                shmaddr 一般为NULL,表示由系统自动完成映射

                                如果不为NULL,那么有用户指定

                shmflg:SHM_RDONLY就是对该共享内存只进行读操作

                             0 可读可写

返回值:成功:完成映射后的地址,

                出错:-1(地址)

用返回值判断用法:if((p =(char*)shmat(shmid,NULL,0))==(char*)-1)

3.4取消映射

int shmdt( constvoid *shmaddr); //detaches

功能:取消映射

参数:要取消的地址

返回值:成功 0

        失败的 -1

3.5删除共享内存

int shmctl( int shmid, int cmd, struct shmid_ds *buf); //control

功能:(删除共享内存),对共享内存进行各种操作

参数:

        shmid 共享内存的id号

        cmd IPC_STAT 获得shmid属性信息,存放在第三参数

                IPC_SET 设置shmid属性信息,要设置的属性放在第三参数

                IPC_RMID 删除共享内存,此时第三个参数为NULL即可

        buf shmid 所指向的共享内存的地址,空间被释放以后地址就赋值为null

返回:成功0

        失败-1

用法: shmctl( shmid, IPC_RMID, NULL);

4.命令

ipcs -m: 查看系统中的共享内存

ipcrm -m shmid:删除共享内存

ps: 可能不能直接删除掉还存在进程使用的共享内存。

这时候可以用 ps -ef对进程进行查看,kill 掉多余的进程后,再使用 ipcs查看。

5.基本操作

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

int main(int argc, char const *argv[])
{

    // 创建key值
    key_t key;
    key = ftok("shm.c", 'd');
    if (key < 0)
    {
        perror("key error");
        return -1;
    }
    printf("key:%#x\n", key);

    // 创建或打开共享内存
    // 不存在创建,存在返回-1
    int shmid;
    shmid = shmget(key, 128, IPC_CREAT | IPC_EXCL | 0777);

    if (shmid <= 0)
    {

        if (errno == EEXIST) // 如果存在,直接打开,返回id
        {
            shmid = shmget(key, 128, 0777);
        }
        else
        {
            perror("shmid error");
            return -1;
        }
    }
    printf("shmid:%d\n", shmid);

    // 映射共享内存
    char *p;
    p = (char *)shmat(shmid, NULL, 0);
    if (p == (char *)-1)
    {
        perror("shmat err");
        return -1;
    }

    // 操作共享内存
    scanf("%s", p);
    // printf("%s \n", p);

    // 取消映射
    shmdt(p);

    // 删除共享内存
    shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

;