1. 共享内存作为进程间通讯的高效方式,在多进程通讯机制中,有信号量、消息队列、套接字和共享内存等方式,但提倡共享内存。

 

2. 共享内存是一个对内存的读写操作,但其需要增加通讯同步方式,例如通过信号量或者线程锁进行同步,因为读写内存都是两个进程或者一个进程内部的两个线程

进行通讯。谈谈线程锁的目的,它主要是通过上锁进行锁定并让其他未上锁的线程进行等待内存的读写完成,因为在一个时刻进行内存读写是不可靠的,会出现数据的异常。

 

3. 阅读具体的shmt代码,第一份是c,第二份是h:

/*
 * Copyright (C) 29178019@qq.com 2022-2023 
 */
#include "shmt.h"

/*
 * @brief init shem
 * @param shmt, data of shmt_operations
 * @param shmt_size, size of shmt
 * @return failed at -1
 */
int shmt_init_mem(struct shmt_operations *shmt, unsigned long shmt_size)
{
    shmt->shmt_key = ftok(SHMT_PATH, 0x6666);

    shmt->shmt_id = shmget(shmt->shmt_key, shmt_size, IPC_CREAT | 0666);
    if ( shmt->shmt_id < 0 )
    {
        printf("failed to get share memory\n");
        return -1;
    }
    if ( shmt_size )
    {
        shmt->shmt_size = shmt_size;
    }

    return 0;
}

/*
 * @brief get address of shmt
 * @param shmt, data of shmt_operations
 * @return failed at NULL
 */
static void *shmt_get_mem_addr(struct shmt_operations *shmt)
{
    void *addr = NULL;
    addr = shmat(shmt->shmt_id,NULL,0);
    if ( !addr )
    {
        printf("faield to map share memory\n");
        return NULL;
    }
    return addr;
}

/*
 * @brief set data to shmt
 * @param msg, msg of setting
 * @param shmt, data of shmt_operations
 * @return failed at -1
 */
int shmt_set_mem_data(struct shmt_operations *shmt,void *msg)
{
    void *addr = NULL;
    addr = shmt_get_mem_addr(shmt);
    if ( NULL == addr )
    {
        printf("failed to get addr of shmem\n");
        return -1;
    }
    memcpy(addr,msg,shmt->shmt_size);
    return 0;
}
/*
 * @brief get data to shmt
 * @param shm, data of shmt_operations
 * @param rsp, msg of getting
 * @return failed at -1
 */
int shmt_get_mem_data(struct shmt_operations *shmt,void *msg)
{
    void *addr = NULL;
    addr = shmt_get_mem_addr(shmt);
    if ( NULL == addr )
    {
        printf("failed to get addr of shmem\n");
        return -1;
    }
    memcpy(msg,addr,shmt->shmt_size);
    return 0;
}

//sample
int main(void)
{
    struct shmt_operations mem = { 0 };
    int ret = -1;
    char set[128] = "talk is cheap, show me the code";
    char get[128] = "";

    ret = shmt_init_mem(&mem,128);
    if ( -1 == ret )
    {
        printf("CziShm_InitShmem failed\n");
        return -1;
    }

    ret = shmt_set_mem_data(&mem,set);
    if ( -1 == ret )
    {
        printf("CziShm_SetShmemData failed\n");
        return -1;
    }

    ret = shmt_get_mem_data(&mem,get);
    if ( -1 == ret )
    {
        printf("CziShm_GetShmemData failed\n");
        return -1;
    }
    printf("the set is %s\n",set);
    printf("the get is %s\n",get);

    return 0;
}

 

/*
 * Copyright (C) 291178019@qq.com 2022-2023 
 */
#ifndef _SHMT_H_
#define _SHMT_H_

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

#define SHMT_PATH "/home/lzh/test/advanced_shmt/src"
#define SHMT_SIZE 1024 * 1024 * 10

struct shmt_operations
{
    key_t shmt_key;            /* key of mem */
    int shmt_id;               /* id of shmt */
    unsigned long shmt_size;   /* size of shmt */

    /* lock etc.. */
};

/* extern functions */
int shmt_init_mem(struct shmt_operations *so, unsigned long size);
int shmt_set_mem_data(struct shmt_operations *so, void *msg);
int shmt_get_mem_data(struct shmt_operations *so, void *msg);

#endif /* _SHMT_H_ */

 该测试代码提供三个封装的接口,该版本是没有线程锁的处理。

可能此时有一种线程锁不应该是在线程之间才可以利用?

没错,shmt_set_mem_data和shmt_get_mem_data都是要在不一样的线程进行操作,但可以并列。

如同a线程可以set,也可以get,但是a线程set,b线程不可以set。

 

4. 加入lock的版本:

 

 可以查看该补丁,即可完成锁版本的共享内存。