Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中向POSIX共享内存对象添加一维数组_C_Posix_Shared Memory - Fatal编程技术网

在C中向POSIX共享内存对象添加一维数组

在C中向POSIX共享内存对象添加一维数组,c,posix,shared-memory,C,Posix,Shared Memory,我正在开发一个基于POSIX的程序,它在两个或多个进程之间共享一个内存对象,也就是服务器-客户机程序 我对程序的服务器端有一些问题。我知道如何使用mmap()映射内存,以及如何在两个不同的进程/程序之间使用对象。但是,在向共享内存对象添加整数数组时,我遇到了一个问题 我可以使用sprintf()将内容打印到共享内存对象,然后通过简单地说ptr+=strlen(whatstringiamworkingwith)来增加(重新分配)共享内存对象的空间 但是,当对象包含C中的整数数组时,我不知道如何将内

我正在开发一个基于POSIX的程序,它在两个或多个进程之间共享一个内存对象,也就是服务器-客户机程序

我对程序的服务器端有一些问题。我知道如何使用
mmap()
映射内存,以及如何在两个不同的进程/程序之间使用对象。但是,在向共享内存对象添加整数数组时,我遇到了一个问题

我可以使用
sprintf()
将内容打印到共享内存对象,然后通过简单地说
ptr+=strlen(whatstringiamworkingwith)来增加(重新分配)共享内存对象的空间

但是,当对象包含C中的整数数组时,我不知道如何将内存重新分配给该对象。下面是我的程序:

#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

int *calcCollatz(int n) {
    int solution;

    int *collatzSeq = malloc(sizeof(int));
    int j = 0;

    while (n != 1) {
        if (n % 2 == 0) {
            solution = n / 2;
            n = solution;
            collatzSeq[j] = n;
            j++;
            return collatzSeq;
        } else {
            solution = (3 * n) + 1;
            n = solution;
            collatzSeq[j] = n;
            j++;
            return collatzSeq;
        }
    }
}

int main(int argc, char *argv[])
{
    const int SIZE = 4096;          //size in bytes of Shared Memory Object
    const char *sharedObj = "Shm";  //name of the Shared memory Object
    int shm_fd;                     //Shared memory file descriptor
    void *ptrShm; //Pointer to shared memory object

    shm_fd = shm_open(sharedObj, O_CREAT | O_RDWR, 0666); //Create Shared Memory Object
    ftruncate(shm_fd, SIZE);  //configure the size of the shared memory object
                              //Map the shared memory object in the space of the process
    ptrShm = mmap(0, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);

    if (ptrShm == MAP_FAILED) {
        printf("Map Failed\n");
        return -1;
    }

    sprintf(ptrShm, argv[1]);
    ptrShm += strlen(argv[1]);

    sprintf(ptrShm, calcCollatz(atoi(argv[1])));
    ptrShm += sizeof(calcCollatz(atoi(argv[1])));


    printf("Writing the sequence to a shared memory object!\n");
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int*calcCollatz(int n){
int解;
int*collatzSeq=malloc(sizeof(int));
int j=0;
而(n!=1){
如果(n%2==0){
溶液=n/2;
n=溶液;
collatzSeq[j]=n;
j++;
返回序列;
}否则{
溶液=(3*n)+1;
n=溶液;
collatzSeq[j]=n;
j++;
返回序列;
}
}
}
int main(int argc,char*argv[])
{
const int SIZE=4096;//共享内存对象的大小(字节)
const char*sharedObj=“Shm”//共享内存对象的名称
int shm_fd;//共享内存文件描述符
void*ptrShm;//指向共享内存对象的指针
shm_fd=shm_open(sharedObj,O_Create | O_RDWR,0666);//创建共享内存对象
ftruncate(shm_fd,SIZE);//配置共享内存对象的大小
//在进程空间中映射共享内存对象
ptrShm=mmap(0,大小,保护写入,映射共享,shm\u fd,0);
如果(ptrShm==MAP_失败){
printf(“映射失败\n”);
返回-1;
}
sprintf(ptrShm,argv[1]);
ptrShm+=strlen(argv[1]);
sprintf(ptrShm,calcCollatz(atoi(argv[1]));
ptrShm+=sizeof(calcCollatz(atoi(argv[1]));
printf(“将序列写入共享内存对象!\n”);
返回0;
}

我的思路是否正确?

您的代码中存在一些错误和问题

  • ptr+=strlen(与什么相关)正在推进指针,而不是
    重新分配内存

  • sprintf(ptrShm,argv[1])是危险的
    如下所示:
    /yourprogram%s
    ,则您将有未定义的行为作为
    %s
    说明符将存在,但指向满足说明符要求的
    char*
    的指针不存在 丢失的切勿将用户填写的变量作为
    printf
    & 这样做:

    sprintf(ptrShm, "%s", argv[1]);
    
    fprintf(stderr, "Map failed: %s\n", strerrno(errno));
    // or
    perror("Map failed");
    
    Sames这样说:
    sprintf(ptrShm,calcCollatz(atoi(argv[1]))

    如果您没有检查是否有足够的命令行参数,您应该 在程序开始时添加以下内容:

    if(argc != 2)
    {
        fprintf(stderr, "usage: %s data\n", argv[0]);
        return 1;
    }
    
  • 错误消息应该打印到
    stderr
    ,而不是
    printf(“映射失败\n”)您应该执行以下操作:

    fprintf(stderr, "Map failed\n");
    
    但这不是很有用,您还应该打印
    errno
    像这样:

    sprintf(ptrShm, "%s", argv[1]);
    
    fprintf(stderr, "Map failed: %s\n", strerrno(errno));
    // or
    perror("Map failed");
    
  • 您没有检查返回值
    shm\u open

  • 退出代码是有符号的8位值,因此执行
    return-1
    相当于
    返回255

  • shm_open
    手册页所述:

    文轩酒店

    共享内存对象应以
    /somename
    的形式标识;也就是说,以null结尾的字符串最多为 NAME_MAX(即255个)字符,由一个初始斜杠组成,后跟一个或多个字符,其中没有一个是斜杠

    所以正确的名字应该是

    const char *sharedObj = "/Shm";
    
  • sizeof(calcCollatz(atoi(argv[1]))
    与sizeof(int*)
  • 相同,即 表示指向
    int
    的指针的大小。因为
    sizeof
    是在 编译时,函数实际上从未执行过。您可能希望按数字调整大小 物品的数量。不仅是
    ptr+=size
    是错误的呼叫,您还得到了 信息完全错误

    您的
    calcCollatz
    也是错误的,您只为一个单独的
    int
    ,为什么要为单个
    int
    动态分配空间呢? 而且你现在正在做
    return collatzSeq
    ,再说一遍,为什么还要麻烦呢 为单个
    int
    动态分配空间?我想这就是你想要的 寻找:

    int *calcCollatz(int n, size_t *len) {
        if(len == NULL)
            return NULL;
    
        int *collatzSeq = NULL, *tmp = NULL;
        *len = 0;
    
        while (n != 1) {
            // better than n % 2 == 0
            if (n & 1 == 0)
                n /= 2;
            else
                n = 3 * n + 1;
    
            tmp = realloc(collatzSeq, (*len + 1) * sizeof *collatzSeq);
            if(tmp == NULL)
            {
                free(collatzSeq);
                return NULL;
            }
            collatzSeq = tmp;
    
            collatzSeq[(*len)++] = n;
        }
    
        return collatzSeq;
    }
    
  • 我真的不明白为什么要调整mmap内存的大小。通常你 立即知道您需要多少内存,以及是否需要动态存储 生成数组,然后计算所需的内存量,然后创建 共享内存,而不是相反的方式:

    size_t base = 4096;
    size_t arrlen;
    
    int *arr = calcCollatz(atoi(argv[1]), &arrlen);
    if(arr == NULL)
    {
        fprintf(stderr, "failed to do calculation\n");
        return 1;
    }
    
    size_t size = base + arrlen;
    
    shm_fd = shm_open(sharedObj, O_CREAT | O_RDWR, 0666);
    if(shm_fd == -1)
    {
        fprintf(stderr, "Failed to open shared memory: %s\n", strerror(errno));
        return 1;
    }
    ftruncate(shm_fd, size);
    
    ptrShm = mmap(0, size, PROT_WRITE, MAP_SHARED, shm_fd, 0);
    
    if (ptrShm == MAP_FAILED) {
        fprintf(stderr, "Map Failed: %s\n", strerror(errno));
        return 1;
    }
    
    printf("Writing the sequence to a shared memory object!\n");
    sprintf(ptrShm, "%s", argv[1]);
    
    // note that void* arithmetic is a GNU extension
    // otherwise you have to cast to (char*) before doing the
    // the arithmetic
    memcpy(ptrShm + base, arr, arrlen * sizeof *arr);
    
    free(arr);
    close(shm_fd);
    return 0;
    
    但是如果您坚持以后调整mmap内存的大小,那么您可以使用 ,但请注意,这仅在GNU/Linux中可用,并且 在包含
    sys/mman.h
    之前,必须添加
    #定义"GNU"源代码

    size_t size = 4096;
    
    // create shared memory + mmap
    ...
    
    // exapanding mmap memory
    size_t arrlen;
    
    int *arr = calcCollatz(atoi(argv[1]), &arrlen);
    if(arr == NULL)
    {
        fprintf(stderr, "failed to do calculation\n");
        close(shm_fd);
        return 1;
    }
    
    size_t newsize = size + arrlen * sizeof *arr;
    
    void *newptrShm = mremap(ptrShm, size, newsize, MREMAP_MAYMOVE);
    
    if(newptrShm == MAP_FAILED)
    {
        fprintf(stderr, "Failed to expand memory: %s\n", strerror(errno));
        free(arr);
        close(shm_fd);
        return 1;
    }
    
    ptrShm = newptrShm;
    
    // resize shared file size
    ftruncate(shm_fd, newsize);
    
    memcpy(ptrShm + base, arr, arrlen * sizeof *arr);
    
    free(arr);
    
    ...
    
    另见:和

  • (1) 你似乎对C相当了解。 英语是你的第一语言吗? 你应该知道做
    ptr  += 
    某些东西
    不是“重新分配空间”或“重新分配内存”;它只是移动一个指针。 (2) 既然您是用C(而不是C++)编程,我建议您减少使用“对象”这个词。 (3) 
    main
    中的注释正常。 您的
    calcCollatz
    中缺少注释。 请加一些。 请不要在评论中回复;让你的问题更清楚、更完整。?