【问题标题】:Am I incorrectly using the unnamed semaphore variable?我是否错误地使用了未命名的信号量变量?
【发布时间】:2013-05-26 16:30:23
【问题描述】:

我正在尝试编写一个程序,其中主进程分配一个共享内存,然后分叉 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。这是无序的结果。

这里是代码 sn-p。

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

我没有发现哪里出了问题。我该怎么办?提前谢谢你。

【问题讨论】:

    标签: synchronization shared-memory


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

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

      2. 相关进程之间。

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-02
        • 1970-01-01
        • 2012-08-01
        • 2012-10-20
        • 1970-01-01
        • 2022-11-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多