前一段时间参加一个项目,设计一个热加载配置的功能,配置是在主进程中加载的,现在期望在主进程中重新加载配置子进程也可以生效。
原来的设计方案是:
新增信号处理函数,每次修改完配置,发送重新加载配置的信号,修改标志位,主进程的主循环中判断标志位是否修改。
int g_loadconf = 0;
signal(SIGALRM,(sighandler_t)notify_gracefully_loadconf );
void notify_gracefully_loadconf()
{
g_loadconf = 1;
}
main
{
g_config = mmap();
config_swap = mmap();
main_loop{
if(g_loadconf=1) {
g_loadconf = 0;
//不直接用g_config,因为load_config方法中可能有对g_config每一项逐项赋值,整个函数调用非原子性。
//如果直接对g_config中每项赋值,因为是共享内存,存在子进程可能访问到部分修改后的数据的问题
load_config( config_swap , config_file);
/*直接交换指针*/
temp = g_config;
g_config = config_swap;
config_swap = temp
}
}
}
改完以后发现使用有问题,仔细看了一下,原来g_cong的类型中包含一些非基础类型的变量。如vector、map或未初始化的指针等。
这些非基础的类型使用过程中存在申请动态内存,而动态申请的内存在进程的地址空间内;如在主进程动态申请的内存空间,子进程访问会出错。
所有在使用共享内存的时候,最好保证全部是基础类型,如果存在动态申请内存的操作,可能不适合使用共享内存。