c - 如何在 C 中的进程之间共享一个带有指针的结构?

标签 c struct shared-memory

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

为清楚起见:唯一共享的是整数 lim_thread。其他字段位于我无法访问的内存区域。为什么? 如我所见,指针指向共享的内存区域。

配置.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;
}

配置.c

#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;
}

最佳答案

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

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

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

关于c - 如何在 C 中的进程之间共享一个带有指针的结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33908573/

相关文章:

c - 使用两个不同的状态同步两个进程

c - 两个进程共享内存中的结构体数组

C - 初始化结构数组

c - C 循环中的孪生素数仅给出第一个值

试用软件的编码

c - 如何让strcmp在汇编中返回0

c# - 为什么我在 C# 中得到一个带有幻影类型的 "cycle in the struct layout"?

pointers - 通过将指针传递给 Go 中的函数来获取不同的值

c++ - 有没有办法通过共享内存中的指针到达某个字节?

c - 用于tilemap的VBO(绘制顺序和倾斜的2D航空)