使用SysV信号量时不一致

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用SysV信号量时不一致相关的知识,希望对你有一定的参考价值。

我正在尝试使用SysV信号量和共享内存API来应用我对信号量的理论知识。

简而言之,我在50个进程之间共享一个int大小的内存(由信号量守护),每个进程增加1000次,所以最终我必须有一个1000 * 50 = 50000的最终值,但奇怪的是我有以下值: 49962,49965,49366 ......

这是我的c代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#define SHMSZ sizeof(int) /* Size of an integer*/

int main(){
    key_t key = 241096; /* Hard-coded key */
    int shm_id, sem_id, *shm;
    struct sembuf psem = {0, -1, 0};
    struct sembuf vsem = {0, 1, 0};

    if((shm_id = shmget(key, SHMSZ, IPC_CREAT | 0666)) == -1){
        printf("Err shmget");
        exit(1);
    }

    if((shm = shmat(shm_id, NULL, 0)) == (int *) -1){
        printf("Err shmat");
    }

    *shm = 0; /*Initilize the shared memory*/

    if((sem_id = semget(key, 1, IPC_CREAT | 0666)) == -1){
        printf("Err semget prg");
        exit(1);
    }

    /***Semaphore initialization****/
    semop(sem_id, &vsem, 1); /*set sem_value to 1*/
    /**********************************/

    int i;
    for (i = 0; i < 50; i++){
        pid_t pid = fork();
        if (pid == 0){
            int j;
            for (j = 0; j < 1000; j++){
                semop(sem_id, &psem, 1); /*wait for the semaphore*/
                *shm = *shm + 1;
                semop(sem_id, &vsem, 1); /* signal the semaphore*/
            }
            return 0; /*Whene done incrementing, return */
        }
    }
    while((wait(NULL) != -1)); /*Wait for all children to terminate*/
    printf("--%i--", *shm); /*Print the final value of the shared  memory*/
    return 0;
}
答案

我尝试执行你的代码,按预期打印50000。尝试使用带有密钥的ftok在两个不同的共享内存之间生成非冗余密钥。

key_t key = ftok(FileName, AnyChar); // The program must have the right to access the file.

如果在执行多次执行时获得这些值,那肯定是因为你没有使用ipcrm -a。此命令将删除程序创建的所有新ipcs。

以上是关于使用SysV信号量时不一致的主要内容,如果未能解决你的问题,请参考以下文章

IPC_NOWAIT semop() 缓冲 SysV 进程

从信号处理程序调用 SysV msgsnd

正确删除多个进程使用的 SYS V 信号量

方向更改时不可见的片段

使用 FragmentPagerAdapter 时不调用 Fragment onResume()

调用 add() 方法时不显示片段