2016-11-11 92 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