0

我正在尝试编写一个程序,其中主进程分配一个共享内存,然后分叉 4 次。然后每个进程递增 1,共享内存中的整数变量 500 次。所以整数变量最终保持了 2500。在访问共享内存之前,进程锁定一个信号量,在写入共享内存之后,进程解锁它。但是程序给了我以下结果。

tracking@ubuntu12.04:~/thread$ ./a.out
shared memory value : 500 by 28488 process
shared memory value : 1000 by 28487 process
shared memory value : 2179 by 28490 process
shared memory value : 1500 by 28489 process
shared memory value : 2500 by 28491 process
tracking@ubuntu12.04:~/thread$ ./a.out
shared memory value : 500 by 28493 process
shared memory value : 1000 by 28492 process
shared memory value : 2500 by 28495 process
shared memory value : 1500 by 28494 process
shared memory value : 2000 by 28496 process
tracking@ubuntu12.04:~/thread$ ./a.out
shared memory value : 500 by 28498 process
shared memory value : 1000 by 28497 process
shared memory value : 1500 by 28501 process
shared memory value : 2000 by 28499 process
shared memory value : 2500 by 28500 process

第一个结果显示奇怪的值,2179。我也认为中间结果应该是有序的,因为一次只有一个进程可以访问共享内存。但是第二个结果显示 500、1000、2500、1500、2000。这是无序的结果。

这是代码片段。

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>

#define KEY_NUM 9527
#define MEM_SIZE 4096

int main(int argc, char *argv[])
{
    char        buffer[1024];
    char        *c;
    int         i, n, status;
    pid_t       childpid = 0;
    sem_t       my_lock;
    int         counter = 0;
    int         shm_id;
    void        *shm_addr;

    if( (shm_id = shmget(IPC_PRIVATE, MEM_SIZE, IPC_CREAT | 0666)) == -1)
    {
        printf("fail to allocate a shared memory.\n");
        return -1;
    }

    shm_addr = shmat(shm_id, (void*)0, 0);

    *(int*)shm_addr = 0; // initially 0.

    if( sem_init(&my_lock, 1, 1) == -1)
    {
        perror("Could not initialize mylock semaphore");
        exit(1);
    }

    for(i = 0;  i < 4; i++)
        if(0 == fork()) 
            break;      // child process exit for-loop.

    // entry section
    if( sem_wait(&my_lock) == -1)
    {
        perror("Semaphore invalid");
        exit(1);
    }
    // start of critical section.

    for(i = 0 ; i < 500; i++)
    {
        *(int*)shm_addr = *(int*)shm_addr + 1;
    }
    sprintf(buffer, "shared memory value : %d by %ld process\n", *(int*)shm_addr, (long)getpid());
    write(STDOUT_FILENO, buffer, strlen(buffer) );
    // end of critical section.

    // exit section
    if (sem_post(&my_lock) == -1)
    {
        perror("Semaphore done");
        exit(1);
    }

    // remainder section
    if(childpid > 0)
    {
        for(i = 0 ; i < n ; i++) // wait for all children.
            wait(&status);
        shmctl(shm_id, IPC_RMID, 0); // deallocate the shared memory.
    }
    exit(0);
}

我没发现哪里出了问题。我应该怎么办?先感谢您。

4

2 回答 2

0

您创建的信号量不在共享内存中,因此在fork每个进程之后都有它的单独副本。您需要将计数器和信号量都保存在共享内存中,使用struct.

于 2013-05-26T17:30:00.700 回答
0

首先,您在代码中使用了未命名的信号量。

未命名的信号量可以用于两件事

  1. 一个进程的线程之间。

  2. 相关进程之间。

您在代码中使用了相关流程。

您的代码中的问题是,您不共享信号量变量。

即让一个名为A它的进程具有count变量,然后您使用fork(). 所以现在有两个进程,父进程是 A ,子进程是 let B ,记住fork()进程 A 和 B 都有自己的 count 变量副本。因此,如果进程 A 更改计数变量,则更改不会反映在进程 B 中。

因此,如果您希望流程 A 所做的更改也反映在流程 B 中,那么您就有了共享计数变量。

于 2013-10-11T09:00:20.343 回答