在C语言中的共享内存和缺少MAP_ANONYMOUS?

3
我正在编写一份C语言程序,其中我要将牌分配给n个玩家,这些玩家由n个派生进程表示。我希望他们都分享同一副牌,因此我尝试使用mmap()来跟踪牌的数量,但是我需要在编译该程序的机器上使用另一种方式来存储全局变量,因为该机器不允许使用MAP_ANONYMOUS或MAP_ANON。是否有其他方法可以在共享内存中存储全局变量,而仍然符合C89 / pre Linux 2.4的规范?
我的程序如下:
static int *deck_size;

int pop(int *arr, int *size, int loc)
{
    int i;
    int val = arr[loc];
    for(i = loc; i < (*size - 1); i++)
    {
        arr[i] = arr[(i+1)];
        arr[*size] = '\0';
    }
    *size = *size-1;
    return val;
}

int main(int argc, char* argv[])
{
    pid_t pid, wpid;
    int status, index, players, rdm_card;
    char outbuf[100];
    int deck[] = 
    {1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13};

    deck_size = mmap(NULL, sizeof *deck_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    *deck_size = 52;
    /* reject an execution with no arguments */
    if(argv[1] == NULL)
    {
        write(STDERR_FILENO, "Usage: dealer <n>\n", 18);
        exit(EXIT_FAILURE);
    }
    else
    {
        if( (players = atoi(argv[1])) < 1)
        {
            write(STDERR_FILENO, "n cannot be less than 1\n", 24);
            exit(EXIT_FAILURE);
        }
    }

    srand ( time(NULL) );

    rdm_card = rand() % *deck_size;

    for(index = 0; index < players; index++)
    {
        pid = fork();
        if (pid == 0) {
            sprintf(outbuf, "random card: %d\n", pop(deck, deck_size, rdm_card));
            write(STDOUT_FILENO, outbuf, 17);
            printf("size of deck %d!\n", *deck_size);
            exit(EXIT_SUCCESS);
        } else if (pid < 0) {
            write(STDERR_FILENO, "fork error\n", 11);
            exit(EXIT_FAILURE);
        } else {
            do {
                wpid = waitpid(pid, &status, WUNTRACED);
            } while (!WIFEXITED(status) && !WIFSIGNALED(status));
        }
    }
    return 0;
}

2
你看过 man 2 shmget 吗?它描述了 POSIX shm 之前使用的古老的 System V 共享内存接口。 - that other guy
2
你是否记得定义 _BSD_SOURCE_SVID_SOURCE 以从 <sys/mman.h> 获取 MAP_ANONYMOUS? - Seek Addo
你尝试使用 fork 进程的特定原因是什么?除非这是项目要求(例如编程作业),否则最好使用线程... - user149341
"C89/pre Linux 2.4" - 是比较老的版本,现在很少见。您可以通过gcc -std=c99 ...使用C99吗?C99将允许其他好处,例如在程序中的任意位置初始化变量。 - jww
@jww 很不幸,我的大学课程要求我们的程序编译为C89。我肯定希望能够做得更好! - MSDOStoevsky
1个回答

2

当你仔细阅读MMAP(2)手册时,它明确说明自Linux内核2.4版本起支持使用MAP_ANONYMOUS

仅在Linux内核2.4及以上版本上支持使用MAP_SHARED联合使用MAP_ANONYMOUS

请确保定义_BSD_SOURCE_SVID_SOURCE以获取MAP_ANONYMOUS

#define _BSD_SOURCE

谢谢!我没意识到需要定义那些内容。此外,#define _DEFAULT_SOURCE_BSD_SOURCE_SVID_SOURCE 的更新版本。 - MSDOStoevsky
@MSDOStoevsky - 对于那些宏,有一个全新的兔子洞可以探索 :) 我通常使用 _X_OPEN_SOURCE_POSIX_SOURCE。我发现 _X_OPEN_SOURCE_POSIX_SOURCE 与使用 C 库的 C++ 编译器更兼容。此外,请参阅 GNU 手册中的 1.3.4 功能测试宏。Newlib 与 Glibc 稍有不同。 - jww
但问题说的是“Linux 2.4之前”,这不是指Linux 2.2及更早版本吗? - that other guy
@thatotherguy 你说得对。MAP_ANONYMOUS与MAP_SHARED结合使用是从2.4版本开始的,但在此之前,只要定义了_BSD_SOURCE,它(MAP_ANONYMOUS)也应该适用于他的机器。感谢您指出这一点。 - Seek Addo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接