如何在C中的进程之间使用指针共享结构?

如何在C中的进程之间使用指针共享结构?,c,struct,shared-memory,C,Struct,Shared Memory,我试图将文件放入结构中,但共享内存时遇到问题,因为我可以访问已创建进程中发生映射的字段,但无法访问其他进程中的数组(只能访问int)。我尝试了很多不同的方法,但我接下来介绍的方法对我来说更有意义,因为我正在使用shmget以正确的方式分配内存 为了清楚起见:唯一被共享的是整数lim_线程。其他字段位于我无法访问的内存区域中。为什么? 正如我看到的,指针指向共享的内存区域 configs.txt: Threads = 5 Domains = uc.pt; edu LocalDomain = so.

我试图将文件放入结构中,但共享内存时遇到问题,因为我可以访问已创建进程中发生映射的字段,但无法访问其他进程中的数组(只能访问int)。我尝试了很多不同的方法,但我接下来介绍的方法对我来说更有意义,因为我正在使用shmget以正确的方式分配内存

为了清楚起见:唯一被共享的是整数lim_线程。其他字段位于我无法访问的内存区域中。为什么? 正如我看到的,指针指向共享的内存区域

configs.txt:

Threads = 5
Domains = uc.pt; edu
LocalDomain = so.local
NamedPipeEstatisticas = statistics
结构:

typedef struct configs
{
    int lim_thread;
    char (*valid_domains)[MAX_DOMAIN_SIZE]; //max size for valid domains
    char *domain;
    char *stat_pipe;
    sem_t sem;
} CONFIGS;
主要条款c:

/*Shared memory for configs*/
CONFIGS *_configs;
int _shmid_configs;

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

    pid_t config_pid; //will hold the configuration process id

    _shmid_configs = shmget(IPC_PRIVATE, sizeof(CONFIGS), IPC_CREAT|0666);
    _configs = shmat(_shmid_configs, NULL, 0);
    /*Semaphores*/
    sem_init( &( _configs->sem), 1, 0);
//initializes processes
    if( ( config_pid = fork() ) < 0) {
        perror("Failed creating configuration manager process");
        num_forks++;
    }
    else if( config_pid == 0 ) {
        init_config();
        exit(0);
    }
    sem_wait(&(_configs->sem));

/////////////////////////DEBUG////////////////////////////////
    printf("%d\n", _configs->lim_thread);
    printf("%s\n", *(_configs->valid_domains+1));
    printf("%s\n", _configs->domain);
    printf("%s\n", _configs->stat_pipe);
//////////////////////////////////////////////////////////////
    return 0;
}
/*用于配置的共享内存*/
配置*\u配置;
int_shmid_配置;
int main(int argc,char*argv[]){
pid\u t config\u pid;//将保存配置进程id
_shmid_configs=shmget(IPC_PRIVATE,sizeof(configs),IPC_CREAT | 0666);
_configs=shmat(\u shmid\u configs,NULL,0);
/*信号量*/
sem_init(&(_configs->sem),1,0;
//初始化进程
如果((config_pid=fork())<0){
perror(“创建配置管理器进程失败”);
num_forks++;
}
else if(config_pid==0){
init_config();
出口(0);
}
sem_wait(&(_configs->sem));
/////////////////////////调试////////////////////////////////
printf(“%d\n”,\u configs->lim\u thread);
printf(“%s\n”,*(\u configs->valid\u domains+1));
printf(“%s\n”,\u配置->域);
printf(“%s\n”,\u configs->stat\u pipe);
//////////////////////////////////////////////////////////////
返回0;
}
配置

#define MAX_LINE_SIZE 1000

int init_config() {

    FILE *fp;
    char domains[MAX_LINE_SIZE], line[MAX_LINE_SIZE], *saveptr, *aux_char;
    int count = 0, aux;
    int temp_shmid;

    if( ( fp = fopen( "./configs.txt", "r")) == NULL) {
        perror("Failed to open configs.txt");
        return -1;
    }

    fscanf( fp,"Threads = %d\n", &(_configs->lim_thread)); 

    //To start reading "Domains = "
    fscanf(fp, "Domains = ");

    fgets(domains, MAX_LINE_SIZE, fp);
    domains[strlen(domains) -1] = '\0';

    //counts the number of domains
    for(aux = 0; aux < strlen(domains); aux++) {
        if( domains[aux] == ';' ) {
            count++;
        }
    }
    //creates shared memory for the valid domains
    temp_shmid = shmget(IPC_PRIVATE, (count+1) * sizeof( char[MAX_DOMAIN_SIZE]), IPC_CREAT|0666);
    _configs->valid_domains = shmat( temp_shmid, NULL, 0);

    //copies all the data to the struct
    strcpy( *(_configs->valid_domains), strtok_r(domains, "; ", &saveptr) );
    aux = 1;
    while( ( aux_char = strtok_r( NULL, "; ", &saveptr) ) != NULL) {
        strcpy( *(_configs->valid_domains + aux), aux_char);
        aux++;
    }

    fscanf(fp, "LocalDomain = %s\n", line);
    temp_shmid = shmget(IPC_PRIVATE, (strlen(line) + 1) * sizeof(char), IPC_CREAT|0660);
    _configs->domain = (char*)shmat(temp_shmid, NULL, 0);
    strcpy(_configs->domain, line);

    fscanf(fp, "NamedPipeEstatisticas = %s\n", line);
    temp_shmid = shmget( IPC_PRIVATE, (strlen(line) +1) * sizeof(char), IPC_CREAT|0660);
    _configs->stat_pipe = (char*)shmat(temp_shmid, NULL, 0);
    strcpy(_configs->stat_pipe, line);


    fclose(fp);

    sem_post( &(_configs->sem));

/////////////////////////DEBUG////////////////////////////////
    printf("%d\n", _configs->lim_thread);
    printf("%s\n", *(_configs->valid_domains+1));
    printf("%s\n", _configs->domain);
    printf("%s\n", _configs->stat_pipe);
//////////////////////////////////////////////////////////////


    return 0;
}
#定义最大线条尺寸1000
int init_config(){
文件*fp;
字符域[最大行大小],行[最大行大小],*saveptr,*aux\u字符;
整数计数=0,辅助;
内部温度;
if((fp=fopen(“./configs.txt”,“r”))==NULL){
perror(“无法打开configs.txt”);
返回-1;
}
fscanf(fp,“线程=%d\n”和(_configs->lim_thread));
//开始阅读“域=”
fscanf(fp,“Domains=”);
FGET(域、最大线尺寸、fp);
域[strlen(域)-1]='\0';
//统计域的数量
对于(aux=0;auxvalid\u domains=shmat(temp\u shmid,NULL,0);
//将所有数据复制到结构
strcpy(*(_configs->valid_domains),strtok_r(domains,;,&saveptr));
aux=1;
while((aux_char=strtok_r(NULL,;,&saveptr))!=NULL){
strcpy(*(配置->有效域+辅助),辅助字符);
aux++;
}
fscanf(fp,“LocalDomain=%s\n”,第行);
temp_shmid=shmget(IPC_PRIVATE,(strlen(行)+1)*sizeof(字符),IPC_create | 0660);
_配置->域=(char*)shmat(temp\u shmid,NULL,0);
strcpy(_configs->domain,line);
fscanf(fp,“namedpipestatisticas=%s\n”,第行);
temp_shmid=shmget(IPC_PRIVATE,(strlen(行)+1)*sizeof(字符),IPC_create | 0660);
_configs->stat\u pipe=(char*)shmat(temp\u shmid,NULL,0);
strcpy(_configs->stat_pipe,line);
fclose(fp);
sem_post(&(_configs->sem));
/////////////////////////调试////////////////////////////////
printf(“%d\n”,\u configs->lim\u thread);
printf(“%s\n”,*(\u configs->valid\u domains+1));
printf(“%s\n”,\u配置->域);
printf(“%s\n”,\u configs->stat\u pipe);
//////////////////////////////////////////////////////////////
返回0;
}

正如kaylum指出的,每个进程都可能将共享内存块映射到不同的虚拟地址。因此,指针不能共享,您需要使用偏移量

分配一个共享内存块,将其分为两部分:内容表和数据区。内容表由包含值或(而不是指针)的变量组成,这些变量包含共享内存块开始与数据区域内数据元素开始之间的偏移量

然后,为了获得数据元素的地址,进程只需将其偏移量添加到其地址空间中共享内存块的地址。

您可以做您想做的事情。在创建任何线程之前,只需在主进程/线程中执行所有
shmget/shmat

子线程将继承指针,并且所有线程的值都相同(例如,指针是全局的。也就是说,它们不使用
\u thread
,也不在线程本地存储中)


这个很好用。我在有50多个线程的系统中使用过它,它工作得很好

您不能跨进程边界共享指针。即使指针指向共享内存,这一点也不会改变。另一个进程需要将共享内存映射到其地址空间,并且几乎肯定会在不同的虚拟地址上这样做。因此,您不能将一个进程中创建的映射/地址直接提供给另一个进程。每个进程都需要自己映射到共享内存。那么我应该怎么做呢?如何将文件映射到共享内存?有没有任何办法让它正常工作?问题是,我只知道打开文件后我需要多少文件,我希望智利进程完成所有与此相关的工作,所以我不能在指针的cratiob之前使用shmget。如果你仔细考虑的话,你可以这样做。我认为概念上的问题是将配置读取和shm分配与流程管理结合起来。它们是不同的步骤。在生成任何内容之前调用init_config。它设置shm区域,存储所需的每线程信息,但不启动线程。然后根据init_config读取[并存储]的内容[仅]创建进程。即使您想要一个“主”进程来控制子进程,也要将其作为主线程。或者,从控制进程中激发所有子进程,