【问题标题】:semaphore hogging by one process一个进程占用信号量
【发布时间】:2016-11-11 15:47:16
【问题描述】:

我正在编写一个程序来测试进程间通信,特别是 POSIX 共享内存。我正在使用 POSIX 信号量来同步进程对共享内存的访问。 (我读到 posix sem_open 函数允许您在进程之间使用相同的信号量,只要您使用相同的“名称”标识符。)

问题是 - 当我执行 sem_wait 和 sem_post 一个进程时……另一个进程没有捕获信号量。进程 1 只是占用信号量并释放它,然后自己将其夺回,而不会给其他进程干预的机会。

这是进程 1 的代码

if ((sem1 = sem_open(request->mem_group.sem_name, O_CREAT, 0644, 0)) ==
        SEM_FAILED) {
        perror("sem_open");
        goto finish;
        }

cache = simplecache_get(request->file_path);
    *(int *)mem_shared = cache == -1 ? -1 : 1;
    sem_post(sem);
    sem_wait(sem);
    if (cache == -1) {
        break;


        fprintf(stdout, "File was not found, going to finish\n");
    }


    file_length = lseek(cache, 0, SEEK_END);
    lseek(cache, 0, SEEK_SET);
    *(size_t *)mem_shared = file_length;

    sem_post(sem);
    sem_wait(sem1);

    if (!file_len) {
        goto finish;
    }

    bytes_transferred = 0;
    while (bytes_transferred < file_len) {

                //rest of while loop here which transfers file

这是进程 2 中的代码块,它应该捕获信号量,但没有

sem_wait(sem1);

file_size = *(size_t *)mem_shared;

gfs_sendheader(ctx, GF_OK, file_size);

sem_post(sem1);

if (!file_size) {
    fprintf(stderr, "File is empty. Go to finish");
    break;
}

所以这个想法是——这个进程 2 应该在另一个进程的 post/wait 之间获取信号量——此时共享的 mem 段中有数据并且不是空的。 然而,相反,当它清空 sahred 内存段并删除其中的任何数据时,它会在另一个进程的最后捕获信号量。

我做了很多故障排除并确认 a) 信号量在每个进程中是相同的信号量 b) 进程 1 确实会在某个时候增加信号量,然后捕获相同的信号量并减少它(使用 sem_getvalue 进行检查)

我通过 Oracle VM VirtualBox 在 Ubuntu 虚拟机上运行它。底层笔记本电脑是 Microsoft Surfacebook。

在这个问题上卡了 48 小时,感到非常沮丧。任何关于如何更有策略地调试它的提示或建议也将不胜感激。

【问题讨论】:

    标签: c posix ipc semaphore


    【解决方案1】:

    这没有意义:

    sem_post(sem);
    sem_wait(sem1);
    

    你增加信号量,然后立即减少它。有一个竞争条件,您的任何一个进程都可以通过等待成功(因为 post),但是由于这个进程已经在 CPU 上,所以它可能总是获胜。

    通常一个进程会发布,而另一个会等待。然后第一个进程继续进行,如果第二个进程有更多工作可以再次发布,第二个进程会根据需要等待。如果两个进程需要协调它们的动作(即第一个进程暂停,直到第二个进程表示可以继续),那么您将使用第二个信号量,在这个信号量上,第一个进程总是等待,第二个进程发布。因此,一个特定的进程只会等待或发布一个特定的信号量,而不是两者兼而有之。

    【讨论】:

    • 非常感谢吉列兹。你是对的,我认为我可以像使用互斥锁一样使用它,如果另一个进程在 sem_wait 中,那么它应该排在第一位。感谢您提供非常有用的答案
    • @raf,您不能对发布时哪个进程(或线程)进行任何假设。简要地看,我找不到参考,但如果你在没有这样的假设的情况下编码,你会很安全:-)
    猜你喜欢
    • 1970-01-01
    • 2020-03-21
    • 2016-06-21
    • 1970-01-01
    • 2023-03-27
    • 2012-03-02
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    相关资源
    最近更新 更多