共享内存中不能存储---类中有申请空间的类对象

背景

有一个需求,作为客户端需要从redis集群中获取数据。出于性能的考虑,再客户端初始化阶段,初始化了一个redis连接,后续在连接redis时,可以直接使用该连接,不用再去重新连接redis了。(这里指的连接其实就是初始化一个类对象,然后根据ip+prot连接redis集群)

但是这样的操作有一个问题就是,当有多个客户端连接redis集群时,由于连接数过多,达到redis节点连接数的限制(默认是4096个连接),这里虽然可以修改redis节点连接数的限制,但是还是没有从源头解决问题,当并发达到一定程度,仍然可以达到连接的上限。

看到这里想着是否可以使用连接池,但是我这种情况不适用。

解决方案

方案一

在真正需要从redis中获取数据时,创建连接->执行操作->释放连接,这样确实可以控制住连接数,但是对性能影响较大。

方案二

是否可以将redis连接(一个类对象)放在共享内存中,多个进程共用一个连接,这样就可以将连接数控制住,而且对性能也没有影响。

针对方案2实施测试

在网上找了linux中共享内存的例子,改写了下
共享内存使用,参考:Linux进程间通信——使用共享内存
下面都是模仿上面这个链接中的内容,如果我写的比较复杂,可以参考下这个人写的。
数据结构文件shmdata.h
我想在共享内存中放一些基本类型和复杂的类型(string vector 只要有申请空间的操作就行),看下通过共享内存访问这些复杂的变量是否可以行的通。

#ifndef _SHMDATA_H_HEADER
#define _SHMDATA_H_HEADER
#include <string>
#define TEXT_SZ 2048
class A
{
    public:
    A(const char *ss)
    {
        num =11;
        str = ss;
    }
   const  char* printlog()
    {
        return str;
    }
    void setsss (const char *s)
    {
        str=s;
    }
    int getnum()
    {
        return num;
    }
   const  char* getstr()
    {
        return str;
    }
    int num;
   const  char * str;
   std::string str_string;
};
  struct shared_use_st
  {
        A a;
        int written;//作为一个标志,非0:表示可读,0表示可写
        char text[TEXT_SZ];//记录写入和读取的文本
  };

#endif

从共享内存中读取A类中的变量,查看多进程下是否是基本类型可以获取,而复杂类型不能获取
数据操作文件 shmwrite.cpp
简单描述下,该文件中有
int initConnect()
int get()
pid_t fork_children(int num)

这几个函数,其中initConnect用来初始化共享内存。get从共享内存中获取数据。fork_children创建多个进程
程序是由主进程调用initConnect来初始化共享内存,然后创建3个子进程从共享内存中获取数据(这里没有考虑同步的问题,先看是否可以正常访问)。程序流程是这样的,可以看下下文中的执行结果和程序中最长的那句注释。

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include "shmdata.h"
#include <iostream>
using namespace std;
A *p=NULL;
int initConnect()
{
    int running = 1;
    void *shm = NULL;
    struct shared_use_st *shared = NULL;
    char buffer[BUFSIZ + 1] = "cx test redis connect";//用于保存输入的文本
    int shmid;
    //创建共享内存
    shmid = shmget((key_t)113, sizeof(struct shared_use_st), 0666|IPC_CREAT);
    if(shmid == -1)
    {
        fprintf(stderr, "shmget failed\n");
        exit(EXIT_FAILURE);
    }
    //将共享内存连接到当前进程的地址空间
    shm = shmat(shmid, (void*)0, 0);
    if(shm == (void*)-1)
    {
        fprintf(stderr, "shmat failed\n");
        exit(EXIT_FAILURE);
    }
    printf("Memory attached at %X\n", shm);
    //设置共享内存
    shared = (struct shared_use_st*)shm;
    printf("shared->written = %d\n",shared->written);
    //向共享内存中写入数据
    strncpy(shared->text, buffer, TEXT_SZ);
    shared->written = 1;
    p = new(shared)A("cx");
    printf("if share memery is %s\n",shared->text);
    cout<<"init success"<<endl;
    cout<<"p->num = "<<p->num<<"  p->str = "<<p->str<<endl;
    p->str_string="changxin";
    }
    return -1;
}
int get()
{
    void *shm = NULL;
    struct shared_use_st *shared = NULL;
       int shmid;
    //创建共享内存
    shmid = shmget((key_t)113, sizeof(struct shared_use_st), 0666|IPC_CREAT);
    if(shmid == -1)
    {
        fprintf(stderr, "shmget failed\n");
        exit(EXIT_FAILURE);
    }
    //将共享内存连接到当前进程的地址空间
    shm = shmat(shmid, (void*)0, 0);
    if(shm == (void*)-1)
    {
        fprintf(stderr, "shmat failed\n");
        exit(EXIT_FAILURE);
    }
    printf("\n\nMemory attached at %X\n", shm);
    //设置共享内存
    shared = (struct shared_use_st*)shm;
    p = &(shared->a);
    cout<<"get shared->text = "<<shared->text<<endl;
    printf("p = %x\n",p);
    printf("p_num = %d\n",p->getnum());
    printf("p_str= %s\n",p->getstr());
    cout<<"get p->num = "<<p->num<<"  p->str = "<<p->str<<endl;
    cout<<"get shared->writtten = "<<shared->written<<endl;
    //主要是这一句,用来打印类中的string类型,这个最后只在主进程中打印出来,在子进程中是获取不到这个变量的
    //因为string的内部实现是自己创建的空间,而创建的这个空间只对当前进程有效,对其他进程不是不可用的。
    cout<<"get p->str_string = "<<p->str_string<<endl;
    cout<<endl<<endl;
	//将共享内存和当前进程分离
    if(shmdt(shm) == -1)
    {
        fprintf(stderr, "shmdt failed\n");
        exit(EXIT_FAILURE);
    }
}
//创建num个进程
pid_t fork_children(int num)
{
    int i;
    pid_t pid;

    for (i = 1; i <= num; i++)
    {
        pid = fork();
        if (pid == -1)
            return pid;
        //pid==0 is children process
        if (pid == 0)
            return pid;
    }
    return 1;
}
int main()
{
    pid_t pid;
    pid = fork_children(3);
    //pid =0;
    //主进程操作
    if (pid > 0)
    {
        printf("test %d\n",pid);
        initConnect();
        get();
        return 1;
    }
    //子进程操作
    else if (pid == 0)
    {
        sleep(2);//保证主进程先将共享内存初始化
        get();
        exit(0);
    }
    return 1;
}

编译

g++ shmwrite.cpp -o shmwrite -lm

执行结果
在这里插入图片描述
最后,欢迎大家指正!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值