第二个进程访问时共享内存为空

问题描述 投票:0回答:0

我有一个 C 应用程序,其中一个进程将数据加载到共享内存空间,然后另一个进程访问共享内存以进行进一步处理。 进程 1 运行良好并加载数据,但进程 2 在共享内存结构字段中看到 0。

使用 GDB,我可以看到在进程 1 结束时,数据已加载到共享内存中并且可以访问。但是,当我尝试从第二个进程访问共享内存时,它显示为 0s。

为了分析,我尝试在两个终端上同时使用 GDB 查看共享内存字段,一个在进程 1 的末尾(就在退出 main 之前),当所有数据都已加载时,同时在另一个终端上使用 GDB进程 2 查看共享内存字段。

以下是我找到的-

进程 1 --> 加载共享内存并在程序结束时(退出 main 之前),在 GDB 中,我看到共享内存中的结构已填充

##Address pointed by the dnodes structure pointer 
(gdb) x /10xg &(g_ptr->dct_tu->dnodes)
0x7fff56fbe4b0: 0x00007fff859abc88      0x00007fffbfaee688
0x7fff56fbe4c0: 0x00007fffbfcd6b08      0x00007fffbe591a88
0x7fff56fbe4d0: 0x00007fffbf4d3e88      0x00007fffbfd9a008
0x7fff56fbe4e0: 0x00007fffed264e08      0x00007fffb2e76a88
0x7fff56fbe4f0: 0x00007fffb6b7fa88      0x00007fffb7320c88

##Data at the address 0x7fff859abc88 which is where the dnodes pointer points as in the above screenshot
(gdb) x /100dw &(g_ptr->dct_tu->dnodes[0])
0x7fff859abc88: 0       0       68068068        0
0x7fff859abc98: 68068068        0       0       0
0x7fff859abca8: 0       0       68067   0
0x7fff859abcb8: 76066071        0       87078000        0
0x7fff859abcc8: 1575397555      319731  0       0
0x7fff859abcd8: 77066   0       76066066        0
0x7fff859abce8: 87088000        0       1575397556      319731

进程 2 --> 试图访问进程 1 创建的共享内存 内存地址与进程 1 指向的内存地址匹配,但值全为 0。

##Address pointed by the dnodes structure pointer
(gdb) x /10xg &(shmp->dct_tu->dnodes)
0x7fff5711e4b0: 0x00007fff859abc88      0x00007fffbfaee688
0x7fff5711e4c0: 0x00007fffbfcd6b08      0x00007fffbe591a88
0x7fff5711e4d0: 0x00007fffbf4d3e88      0x00007fffbfd9a008
0x7fff5711e4e0: 0x00007fffed264e08      0x00007fffb2e76a88
0x7fff5711e4f0: 0x00007fffb6b7fa88      0x00007fffb7320c88


##Data at the address 0x7fff859abc88 which is where the dnodes pointer points as in the above screenshot
(gdb) x /100dw &(shmp->dct_tu->dnodes[0])
0x7fff859abc88: 0       0       0       0
0x7fff859abc98: 0       0       0       0
0x7fff859abca8: 0       0       0       0
0x7fff859abcb8: 0       0       0       0
0x7fff859abcc8: 0       0       0       0
0x7fff859abcd8: 0       0       0       0
0x7fff859abce8: 0       0       0       0
0x7fff859abcf8: 0       0       0       0
0x7fff859abd08: 0       0       0       0

进程1代码- 简化过程 1 代码,如果在 main 函数结束时在 GDB 中检查,则填充链接和 dnodes 结构。此 C 文件中包含头文件“appheader.h”结构

#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <math.h>

#define N_LINKAGE_NODES_TU                 1000
#define N_DATA_NODES_TU                    100
#define arraySize                          36+1

typedef struct linkage_node_tu
{
    long     link[10];
} ln_node_t_tu;

typedef struct data_node_tu
{
    unsigned long  code;
    unsigned long sales_account_up;
    unsigned long sales_account_lo;
    long acc_num_tu;
    long link;
} d_node_t_tu;

typedef struct dc_tree_tu
{
    ln_node_t_tu   *links;
    d_node_t_tu    *dnodes;
} dc_tree_t_tu;

typedef struct par_refdata
{
    dc_tree_t_tu dct_tu;
} par_refdata_type;

typedef struct lookup_dict
{
    int iIndex;
    char cCharRep;
} lkup_dict;


extern void load_refdata ();
void load_lookup_array();
long convertAccToLong(char *);

int debug;
lkup_dict lookup_d[arraySize];

int main (int argc, char **argv)
{
        int i;
        int shmget_flag = (IPC_CREAT | IPC_EXCL | 0600);
        int shm_par_refdata_id;
        size_t total_shmem_size;
        size_t g_size;
        size_t tu_l_size;
        size_t tu_d_size;

        char *start_shmem_address;
        par_refdata_type *g_ptr;
        ln_node_t_tu *tu_l_ptr;
        d_node_t_tu *tu_d_ptr;

        char *e_ptr;
        char *end_shmem_address;

        debug = 1;

        g_size = sizeof(par_refdata_type);
        tu_l_size = (sizeof(ln_node_t_tu) * N_LINKAGE_NODES_TU);
        tu_d_size = (sizeof(d_node_t_tu) * N_DATA_NODES_TU);
        total_shmem_size = g_size + tu_l_size + tu_d_size;

        if (debug)
        {
                printf("PROCESS1_SHM : g_size = %lu\n", g_size);
                printf("PROCESS1_SHM : tu_l_size = %lu\n", tu_l_size);
                printf("PROCESS1_SHM : tu_d_size = %lu\n", tu_d_size);
                printf("PROCESS1_SHM : total_shmem_size = %lu\n", total_shmem_size);
                printf("PROCESS1_SHM : N_LINKAGE_NODES_TU <%d>, sizeof(ln_node_t_tu) <%zu>\n",N_LINKAGE_NODES_TU, sizeof(ln_node_t_tu));
        }

        //set up Shared mem
        shm_par_refdata_id = shmget( 0x2a0e4150,total_shmem_size,shmget_flag);

        if (shm_par_refdata_id == -1)
        {
            printf("PROCESS1_SHM : unable to shmget gather refdata, errno = %d ", errno);
            exit (EXIT_FAILURE);
        }

        if((start_shmem_address = shmat (shm_par_refdata_id,0,0)) == (void *)-1)
        {
            printf("unable to shmat gather refdata, errno = %d ",errno);
            exit (EXIT_FAILURE);
        }

        end_shmem_address = start_shmem_address + total_shmem_size;

        printf("PROCESS1_SHM : start_shmem_address = %u\n", start_shmem_address);
        printf("PROCESS1_SHM : end_shmem_address = %u\n", end_shmem_address);
        printf("PROCESS1_SHM : total_shmem_size = %lu\n", total_shmem_size);

        //Initialize the pointers to the various structures in shared memory
        g_ptr = (par_refdata_type *) start_shmem_address;
        tu_l_ptr = (ln_node_t_tu *)(intptr_t)((unsigned long)g_ptr + (unsigned long)g_size);
        tu_d_ptr = (d_node_t_tu *)(intptr_t)((unsigned long)tu_l_ptr + (unsigned long)tu_l_size);
        e_ptr = (char *)(intptr_t)((unsigned long)tu_d_ptr + (unsigned long)tu_d_size);

        (g_ptr->dct_tu).links=tu_l_ptr;
        (g_ptr->dct_tu).dnodes=tu_d_ptr;
        if (debug)
        {
                printf("PROCESS1_SHM : g_ptr = %u\n", g_ptr);
                printf("PROCESS1_SHM : tu_l_ptr = %u\n", tu_l_ptr);
                printf("PROCESS1_SHM : tu_d_ptr = %u\n", tu_d_ptr);
                printf("PROCESS1_SHM : e_ptr = %u\n", e_ptr);
        }

        if(e_ptr > (start_shmem_address + total_shmem_size))
        {
                printf("Shared memory required exceeds shared memory requested-Exiting ");
                exit (EXIT_FAILURE);
        }

        /*Load the shared memory with the reference data */
        load_refdata (start_shmem_address);

        exit (EXIT_SUCCESS);

}    /* main */



void load_refdata( par_refdata_type *g_ptr)
{
        FILE    *fp;
        long cur_dnode;
        long cur_lnode;
        long nxt_lnode;
        long free_lnode;
        long last_lnode;
        long new_addr;
        long free_dnode;
        unsigned long  tu_code;
        char    cli[100];
        int cli_len;
        int discard;
        int rec_cnt;
        int digit;
        long val;
        char tu_char[3];
        int code_val;
        unsigned long tu_sales_up;
        unsigned long tu_sales_lo;
        char sales_char[7];
        long sales_val_up;
        long sales_val_lo;
        long sales_acc_int;
        dc_tree_t_tu *dt_ptr_tu;
        char cd_ref_file[100];
        char lbuf[BUFSIZ];
        int records_read;

        char csAccNum[16];
        long llaccntNum;
        llaccntNum=0ll;
        load_lookup_array();

        strcpy(cd_ref_file, "/c/projects/refdat");

        if ((fp = fopen(cd_ref_file,"r")) == NULL)
        {
                printf("open failed for %s (errno=%d)",cd_ref_file, errno);
                exit (EXIT_FAILURE);
        }

        dt_ptr_tu = &(g_ptr->dct_tu);

        /*  Initialize structures */
        for (cur_lnode = 0; cur_lnode < N_LINKAGE_NODES_TU; cur_lnode++)
        {
                for (digit = 0; digit < 10; digit++)
                {
                        dt_ptr_tu->links[cur_lnode].link[digit] = 0;
                }
        }

        sales_acc_int = 68068068;
        for (cur_dnode = 0; cur_dnode < N_DATA_NODES_TU; cur_dnode++)
        {
                dt_ptr_tu->dnodes[cur_dnode].code = 0;
                dt_ptr_tu->dnodes[cur_dnode].link = 0;
                dt_ptr_tu->dnodes[cur_dnode].acc_num_tu = 0ll;
                dt_ptr_tu->dnodes[cur_dnode].sales_account_up = sales_acc_int;
                dt_ptr_tu->dnodes[cur_dnode].sales_account_lo = sales_acc_int;
        }

        free_lnode = 1;
        free_dnode = 1;
        rec_cnt = 0;

        records_read = 0;
        while (records_read < N_DATA_NODES_TU && fgets(lbuf, sizeof(lbuf), fp) != NULL)
        {
                //E.g. lines from file -> 0012345670 DX LBRZ1 WX11237882
                sscanf(lbuf, "%s %s %s %s", cli, tu_char,sales_char, csAccNum);
                rec_cnt++;
                records_read++ ;
                code_val=tu_char[0]*1000+tu_char[1];
                sales_val_up= sales_char[0]*1000000 + sales_char[1]*1000 + sales_char[2];
                sales_val_lo= sales_char[3]*1000000 + sales_char[4]*1000 + sales_char[5];
                llaccntNum=convertAccToLong(csAccNum);


                tu_code = code_val;
                tu_sales_up = sales_val_up;
                tu_sales_lo = sales_val_lo;

                cli_len = strlen(cli);
                cur_lnode = 0;
                last_lnode = 0;
                discard = 0;

                for (digit = 0; (digit < cli_len) && (discard == 0); digit++)
                {
                        val = cli[digit] - '0';
                        new_addr = dt_ptr_tu->links[cur_lnode].link[val];

                        if (new_addr < 0)
                        {
                                cur_dnode = -new_addr;
                                if (digit == (cli_len - 1))
                                {

                                        if (tu_code != dt_ptr_tu->dnodes[cur_dnode].code)
                                        {
                                                discard = 1;
                                                printf("duplicate tu found %ld",tu_code);
                                        }
                                        continue;
                                }


                                if (dt_ptr_tu->dnodes[cur_dnode].link == 0)
                                {
                                        if (free_lnode == N_LINKAGE_NODES_TU)
                                        {
                                                fclose(fp);
                                                printf("Out of LNODES for TU at record %d",rec_cnt);
                                                return;
                                        }
                                        dt_ptr_tu->dnodes[cur_dnode].link= free_lnode++;
                                }

                                nxt_lnode = dt_ptr_tu->dnodes[cur_dnode].link;


                                cur_lnode = nxt_lnode;
                                continue;
                        }

                        if (new_addr == 0)
                        {
                                if (free_lnode == N_LINKAGE_NODES_TU)
                                {
                                        fclose(fp);
                                        printf("Out of LNODES for TU at record %d",rec_cnt);
                                        return;
                                }
                                nxt_lnode = free_lnode++;
                                dt_ptr_tu->links[last_lnode].link[val] = nxt_lnode;
                                last_lnode = cur_lnode;
                                cur_lnode = nxt_lnode;
                                continue;
                        }
                        cur_lnode = new_addr;
                }

                if (discard == 1)
                {
                        printf("Duplicate cli %s at line %d",cli,rec_cnt);
                }
                else
                {
                        if (free_dnode == N_DATA_NODES_TU)
                        {
                                fclose(fp);
                                printf("Out of DNODES for TU at record %d",rec_cnt);
                                return;
                        }
                        dt_ptr_tu->dnodes[free_dnode].code = tu_code;
                        dt_ptr_tu->dnodes[free_dnode].sales_account_up = tu_sales_up;
                        dt_ptr_tu->dnodes[free_dnode].sales_account_lo = tu_sales_lo;
                        dt_ptr_tu->dnodes[free_dnode].acc_num_tu = llaccntNum;
                        dt_ptr_tu->links[last_lnode].link[val] = -free_dnode;
                        free_dnode++;
                        free_lnode--;
                }
        }

        fclose(fp);

        return;
}


long convertAccToLong(char *csAccNum)
{
    int i, j;
    long out=0ll;

    for ( i=strlen(csAccNum)-1; i >= 0  ; i--)
    {
        for ( j=0; j < arraySize-1  ; j++)
        {
            if (lookup_d[j].cCharRep == csAccNum[i])
            {
                out += (lookup_d[j].iIndex * pow(36,(strlen(csAccNum)-1 - i)));
                break;
            }
        }
    }

    if ( out > 9223372036854775807ll )
        printf("out <%ld> for acc <%s>\n",out, csAccNum);

    return out;
}

void load_lookup_array()
{
    int i;
    char charArray[arraySize];


    strcpy(charArray,"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");

    for ( i=0; i < arraySize ; i++)
    {
        lookup_d[i].iIndex=i;
        lookup_d[i].cCharRep=charArray[i];
    }
}

进程2代码- 进程 2 代码访问由进程 1 填充的共享内存。一旦连接了共享内存,在 GDB 中使用它来检查共享内存字段。

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

#include"appheader.h"


#define BUF_SIZE 2962799112
#define SHM_KEY 0x2a0e4150

struct shmseg {
   int cnt;
   int complete;
   char buf[BUF_SIZE];
};

int main(int argc, char *argv[]) {
   int shmid;
   gather_refdata_type *shmp;
   shmid = shmget(SHM_KEY, SHM_DATA_SIZE, 0600);
   if (shmid == -1) {
      perror("Shared memory get failed");
      return 1;
   }

   shmp = shmat(shmid, NULL, 0);
   if (shmp == (void *) -1) {
      perror("Shared memory attach failed");
      return 1;
   }

   printf("shmp->dct_tu.links->link[0] <%ld>\n",*(shmp->dct_tu.links->link[0]));
   printf("Reading Process: Reading Done, Detaching Shared Memory\n");


   return 0;
}

ipcs命令输出-

$ ipcs

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x2a0e4150 0          dev01   600        2962799112 2

------ Semaphore Arrays --------
key        semid      owner      perms      nsems

我无法理解为什么相同的内存地址在进程 1 访问时似乎已填充,但同时在进程 2 查看时似乎为 0。

c shared-memory
© www.soinside.com 2019 - 2024. All rights reserved.