2016-11-11 107 views
0

我正在编写一个程序来测试进程间通信,特别是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之间获取seemaphore--在这一点上共享的mem段有数据并且不是空的。然而,相反,它在其他进程的最后一端捕获信号量,此时它清空了内存段并删除了内部的任何数据。

我做了很多的麻烦拍摄的,并证实 A)的信号是在每个进程 B中的相同信号)顺序1确实在某一时刻的增量信号,再搭上同一个信号和递减它(选中这与sem_getvalue)

我是一个Ubuntu的虚拟机上通过的Oracle VM VirtualBox运行此。底层笔记本电脑是微软Surfacebook。

一直停留在这个问题上48小时,感到非常沮丧。任何有关如何更具战略性地调试它的技巧或建议也将不胜感激。

回答

0

这是没有意义的:

sem_post(sem); 
sem_wait(sem1); 

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

通常一个过程会发布,另一个会等待。然后第一个过程继续进行,如果第二个过程有更多的工作,可以根据需要等待。如果两个进程需要协调他们的行为(即第一个进程暂停,直到第二个进程停止,那么你就可以使用第二个信号量,在这个进程上,第一个进程总是等待,第二个进程也是。所以一个特定的进程只能等待或发布特定的信号量,从来都不是。

+0

非常感谢你gilez。你是对的,我想我可以像互斥体一样使用它,并且如果另一个进程在sem_wait中,那么它应该是第一个在线。 感谢您一个非常有用的答案 – rafiya

+0

@raf,你不能做任何假设哪些进程(或线程)将获得当您发布去。简单地看,我找不到参考,但如果你没有这样的假设编码,你会安全的:-) – gilez