一个进程占用信号量
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,永远不会两者都等待。
我正在编写一个程序来测试进程间通信,特别是 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,永远不会两者都等待。