一个进程占用信号量

semaphore hogging by one process

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

问题是 - 当我执行 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 之间获取信号量——此时共享内存段中有数据并且不为空。 然而,相反,当它清空 sahred 内存段并删除其中的所有数据时,它会在另一个进程的最后捕获信号量。

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

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

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

这没有意义:

sem_post(sem);
sem_wait(sem1);

你递增信号量,然后立即递减它。存在竞争条件,您的任何一个进程都可能成功等待(因为 post),但由于此进程已经在 CPU 上,也许它总是获胜。

通常一个进程会 post,另一个会等待。然后第一个进程继续,如果第二个进程有更多工作,则可以 post 再次进行,第二个进程根据需要等待。如果这两个进程需要协调它们的操作(即第一个进程暂停,直到第二个进程说可以继续),那么你会使用第二个信号量,在这个信号量上,第一个进程总是等待,第二个 post秒。因此,一个特定的进程只会在特定的信号量上等待或 posts,永远不会两者都等待。