第二十九章 System V共享内存

共享内存数据结构

共享内存函数

shmget

int shmget(key_t key, size_t size, int shmflg);
功能:
    用于创建共享内存
参数:
    key : 这个共享内存段名字
    size : 共享内存大小
    shmflg : 由9个权限位标志构成,它们的用法与创建文件时使用的mode模式标志是一样的
返回值:
    成功 : 返回一个非负整数,即该共享内存段的标识码
    失败 : -1
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#include <sys/ipc.h>
#include <sys/shm.h>

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

typedef struct str
{
    char name[32];
    int age;
}STU;


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

    int shmid;
    shmid = shmget(1234, sizeof(STU), IPC_CREAT|0666);
    if(shmid == -1)
        ERR_EXIT("shmget");

    

    return 0;
}

结果

ipcs

------------ 共享内存段 --------------
键         shmid      拥有者     权限       字节      连接数  状态    
0x000004d2 9011220    dw         666        36         0             

shmat

void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:
    将共享内存段连接到进程地址空间
参数:
    shmid : 共享内存标识
    shmaddr : 指定连接的地址
        NULL : 核心自动选择一个地址
        not NULL && 未设置SHM_RND标记,则以shmaddr为连接地址
        not NULL && 设置了SHM_RND标记,则连接的地址会自动往下调整为SHMLBA的整数倍。公式 : shmaddr - (shmaddr % SHMLBA)
    shmflg : 
        SHM_RND
        SHM_RDONLY : 表示连接操作用来只读共享内存
返回值:
    成功 : 返回一个指针,指向共享内存第一节
    失败 : -1

shmdt

int shmdt(const void *shmaddr)
功能:
    将共享内存段与当前进程脱离
参数:
    shmaddr : 由shmat所返回的指针
返回值:
    成功 : 0
    失败 : -1
注意:
    将共享内存段与当前进程脱离不等于删除共享内存段

shmget_write.c

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

#include <sys/ipc.h>
#include <sys/shm.h>

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

typedef struct str
{
    char name[32];
    int age;
}STU;


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

    int shmid;
    shmid = shmget(1234, sizeof(STU), IPC_CREAT|0666);
    if(shmid == -1)
        ERR_EXIT("shmget");

    STU *p;
    //自动分配地址且可读可写
    p = shmat( shmid, NULL, 0);
    if(p == (void*)-1)
        ERR_EXIT("shmat");

    strcpy(p->name, "xiaoming");
    p->age = 20;

    sleep(10);
    shmdt(p);

    return 0;
}

结果

进程退出前
ipcs
------------ 共享内存段 --------------
键         shmid      拥有者       权限     字节     连接数  状态      
0x000004d2 9011220    dw         666        36         1              

进程退出后
ipcs
------------ 共享内存段 --------------
键         shmid      拥有者       权限     字节     连接数  状态      
0x000004d2 9011220    dw         666        36         0     

shmget_read.c

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

#include <sys/ipc.h>
#include <sys/shm.h>

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

typedef struct str
{
    char name[32];
    int age;
}STU;


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

    int shmid;
    //第二个参数,如果不知道大小可以填0
    // shmid = shmget(1234, sizeof(STU), IPC_CREAT|0666);
    shmid = shmget(1234, 0, 0);
    if(shmid == -1)
        ERR_EXIT("shmget");

    STU *p;
    //自动分配地址且可读可写
    p = shmat( shmid, NULL, 0);
    if(p == (void*)-1)
        ERR_EXIT("shmat");

    printf("name : %s age : %d \n",p->name, p->age);
    
    shmdt(p);

    return 0;
}

shmctl

int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:
    用来控制共享内存
参数:
    shmid : 共享内存标识
    cmd : 要采取的操作
        IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
        IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
        IPC_RMID:删除共享内存段
    buf : 是一个结构指针,它指向共享内存模式和访问权限的结构
返回值:
    成功 : 0
    失败 : -1

共享内存示例

shmget_write.c

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

#include <sys/ipc.h>
#include <sys/shm.h>

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

typedef struct str
{
    char name[32];
    int age;
}STU;


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

    int shmid;
    shmid = shmget(1234, sizeof(STU), IPC_CREAT|0666);
    if(shmid == -1)
        ERR_EXIT("shmget");

    STU *p;
    //自动分配地址且可读可写
    p = shmat( shmid, NULL, 0);
    if(p == (void*)-1)
        ERR_EXIT("shmat");

    strcpy(p->name, "xiaoming");
    p->age = 20;

    while(1)
    {
        if(memcmp(p, "quit", 4) == 0)
            break;
    }

    shmdt(p);
    shmctl(shmid, IPC_RMID, NULL);

    return 0;
}

shmget_read.c

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

#include <sys/ipc.h>
#include <sys/shm.h>

#define ERR_EXIT(m)         \
    do                      \
    {                       \
        perror(m);          \
        exit(EXIT_FAILURE); \
    } while (0)

typedef struct str
{
    char name[32];
    int age;
}STU;


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

    int shmid;
    //第二个参数,如果不知道大小可以填0
    // shmid = shmget(1234, sizeof(STU), IPC_CREAT|0666);
    shmid = shmget(1234, 0, 0);
    if(shmid == -1)
        ERR_EXIT("shmget");

    STU *p;
    //自动分配地址且可读可写
    p = shmat( shmid, NULL, 0);
    if(p == (void*)-1)
        ERR_EXIT("shmat");

    printf("name : %s age : %d \n",p->name, p->age);

    memcpy(p, "quit", 4);

    shmdt(p);

    return 0;
}
posted @ 2019-09-25 13:03  sfdevs  阅读(157)  评论(0编辑  收藏  举报