2017-08-29 100 views
1

有兩個信號量和兩個進程。 「p1sem」表示process1在此信號量上等待並且process2發佈該信號量。 「p2sem」恰恰相反。這兩個進程初始化值爲0(如果它們還沒有被創建)POSIX信號量的奇怪問題

因此,process1運行兩個會話打開和刪除這兩個信號量。 process2只運行一個會話,但應該再次調用以耗盡process1的下一個會話。這是代碼的樣子:

進程2:

#include <semaphore.h> 
#include <fcntl.h> 

int main(){ 
    sem_t *waitSem = sem_open("p2sem", O_CREAT, 0666, 0); 
    sem_t *postSem = sem_open("p1sem", O_CREAT, 0666, 0); 

    // tic for a cycle 
    sem_post(postSem); 
    sem_wait(waitSem); 

    // close and exit 
    sem_close(waitSem); 
    sem_close(postSem); 
    sem_unlink("p2sem"); 
    sem_unlink("p1sem"); 
} 

過程1:

#include <semaphore.h> 
#include <fcntl.h> 

int main() { 
    for(int i = 0; i < 2; i++) { 

     // create sems 
     sem_t *waitSem = sem_open("p1sem", O_CREAT, 0666, 0); 
     sem_t *postSem = sem_open("p2sem", O_CREAT, 0666, 0); 

     // tic for a cycle 
     sem_post(postSem); 
     sem_wait(waitSem); 

     // close and exit 
     sem_close(waitSem); 
     sem_close(postSem); 
     sem_unlink("p2sem"); 
     sem_unlink("p1sem"); 
    } 
} 

爲了讓過程1繼續,過程2有張貼p1sem。 process2也一樣,只有process1發佈它是p2sem才能繼續。這可能聽起來像是某種僵局,但這些帖子是在等待之前發生的,所以這應該不成問題。

當process1第一次啓動,然後我調用process2兩次,事情工作正常。

但是,如果process2首先啓動,那麼第一個會話正常工作,但是當再次調用process2時,兩個進程都會掛起。據我瞭解,這沒有理由發生。當我調試時,懸掛時刻信號量的值是,對於每個進程,對於(即p1sem在process1的值爲0,但在process2的值爲1,對於p2sem是相同的。)我附加了gdb的圖片在信號值的__align =中,我認爲大的正數表示負-1,它是 - 等待該信號量的進程數,至少根據http://man7.org/linux/man-pages/man3/sem_getvalue.3.html)。您還可以通過gdb調用sem_post和sem_wait來玩遊戲但是您會看到無論您調用哪個進程,它都不會影響另一個進程的信號量值。

/dev/shm包含sem.p1sem和sem.p2sem。如果人們想測試這個,然後重新啓動過程中,你必須刪除這些信號與rm sem.p1sem sem.p2sem

有沒有人明白這一點?

enter image description here

回答

1

如果啓動 「PROC2」,然後 「PROC1」,它看起來像:

  • 「PROC1」 當選,因此解除鏈接信號燈,然後創建新的,
  • 然後「proc2」被選中並且斷開新創建的信號量
  • 因此「proc2」的新實例創建與先前無關的新信號量。這是由sem_open規定:

如果一個過程使重複調用sem_open(),具有相同的名稱 的說法,同樣的描述符返回每次成功通話,除非 sem_unlink()被調用在信號量的過渡期間。

「PROC1」隨後被阻塞等待信號量即沒有更多的可訪問的任何其他過程。

+0

感謝您的回答! 我還是不明白第三步。事情是,這些被命名爲信號量,所以除非我失去了一些東西,那麼它們不應該與以前的東西無關,因爲它們具有相同的名稱(p1sem,p2sem) 另外,在第一次,當proc1取消鏈接時,它不會從操作系統中刪除信號量,因爲它們仍可從proc2訪問。所以當它繼續創建「新的」時,它們並不是真正的新的,sem_open應該返回那裏已經存在的信號量。 (O_CREAT標誌意味着它應該創建信號量,如果它不存在) – burnedWood

+1

唉不,這就像文件一樣,如果你刪除它然後重新創建它就是不同的文件。來自'sem_open'手冊的引用*如果進程對sem_open()進行重複調用,並且名稱相同,則每次成功調用都會返回相同的描述符,除非在信號量上調用了sem_unlink()臨時。* –

+0

謝謝Jean-Baptiste,我現在明白了! – burnedWood