2012-12-03 30 views
2

我有過程的這個圖。在每個線程中都有新的過程開始第一是流程1,當它結束信號量發佈,下一個可能的過程是2和4
此圖解釋更多:1http://i49.tinypic.com/34t5uo0.png。我的腳本在一些倍崩潰。過程1,2或4不執行。問題在哪裏?信號燈+並行線程,不能正常工作

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <semaphore.h> 




sem_t semA,semB,semC,semD,semE; 


void* process_2 (void* param) 
{ 
    sem_wait(&semA); 
    int pid2, status2; 
    pid2 = fork(); 
    if (pid2 < 0) { 
    exit(1); 
    } 
if (pid2==0) { 

    printf("Process 2\n"); 
    } 
else { 
    wait(&status2); 
    sem_post(&semC); 
} 
return NULL; 
} 

void* process_4(void* param) 
{ 
sem_wait(&semB); 
int pid4, status4; 
pid4 = fork(); 
if (pid4 < 0) { 
    exit(1); 
} 
if (pid4==0) { 

    printf("Process 4\n"); 


    exit(0); 
} 
else { 
    wait(&status4); 
    sem_post(&semD);       
} 


return NULL; 
} 


void* process_3(void* param) 
{ 
sem_wait(&semC); 
int pid3, status3; 
pid3 = fork(); 
    if (pid3 < 0) { 
    exit(0); 
} 
if (pid3 == 0) { 

    printf("Process 3\n"); 
} 
else{ 
    wait(&status3); 
    sem_post(&semE); 
} 

return NULL; 

} 

void* process_5(void* param) 
{ 
sem_wait(&semD); 
sem_wait(&semE); 
int pid5, status5; 
pid5 = fork(); 
if (pid5 < 0) { 
    exit(0); 
} 
if (pid5 == 0) { 
    printf("Process 5\n"); 
} 
else{ 
    wait(&status5); 
    exit(0); 
} 

return NULL; 

} 



int main() { 

    pthread_t thread_id[4]; 
    pthread_create(&thread_id[0], NULL,&process_2, NULL); 
    pthread_create(&thread_id[1], NULL,&process_3, NULL); 
    pthread_create(&thread_id[2], NULL,&process_4, NULL); 
    pthread_create(&thread_id[3], NULL,&process_5, NULL); 


    sem_init(&semA,0,0); 
    sem_init(&semB,0,0); 
    sem_init(&semC,0,0); 
    sem_init(&semD,0,0); 
    sem_init(&semE,0,0); 


    int pid, status; 


    pid = fork(); 
    if (pid < 0) { 
    exit(1); 
    } 
    if (pid==0) { 
    printf("Process 1\n");  
    } 
    else { 
    wait(&status); 
    sem_post(&semA); 
    sem_post(&semB); 
    int i; 
    for (i = 0; i < 4; i++) 
    pthread_join(thread_id[i],NULL); 
    return 0; 
    } 
exit(0); 

} 

回答

3

至少有一個問題是你在初始化之前信號燈產卵線程:

pthread_t thread_id[4]; 
pthread_create(&thread_id[0], NULL,&process_2, NULL); 
pthread_create(&thread_id[1], NULL,&process_3, NULL); 
pthread_create(&thread_id[2], NULL,&process_4, NULL); 
pthread_create(&thread_id[3], NULL,&process_5, NULL); 


sem_init(&semA,0,0); 
sem_init(&semB,0,0); 
sem_init(&semC,0,0); 
sem_init(&semD,0,0); 
sem_init(&semE,0,0); 

這在主線程初始化信號量和使用它們的子線程之間的競爭條件。在這裏使用未初始化的數據是一個非常好的機會。

我建議您在main()函數交換順序:

pthread_t thread_id[4]; 

sem_init(&semA,0,0); 
sem_init(&semB,0,0); 
sem_init(&semC,0,0); 
sem_init(&semD,0,0); 
sem_init(&semE,0,0); 

pthread_create(&thread_id[0], NULL,&process_2, NULL); 
pthread_create(&thread_id[1], NULL,&process_3, NULL); 
pthread_create(&thread_id[2], NULL,&process_4, NULL); 
pthread_create(&thread_id[3], NULL,&process_5, NULL); 
+1

它正在工作,非常感謝! –

+0

這隻記錄你在代碼中遇到的部分問題。我將它們列在單獨的答案中,因爲在評論中列出的時間太長。 –

2

Ben的回答顯示了你的主要問題,但你有別人。您正在使用線程,進程和信號量進行編程非常容易。

  • 信號量不是這樣編程的。所有的信號量函數 都給出了錯誤返回碼的一個很好的理由。 E.g sem_wait 如果該進程接收到一個信號可以encouter「虛假喚醒」。所以 你必須檢查回報,然後errno看看發生了什麼, 編程POSIX信號燈時沒有辦法解決這個問題。

  • 信號只是POSIX中的一個可選功能。這可能是 更容易從一開始就設計成它的POSIX功能 開始,即pthread_mutex_tpthread_cond_t。 你作爲補充獲得的是可移植性。仍然有很多不支持信號量的常見體系結構。

  • 的方式你正在做這共享信號燈 進程之間的方式:

    父的整個虛擬地址空間中的孩子複製

    這意味着子項中的信號量是一個副本,並且這兩個進程將無法通過它進行通信。你必須 使用類似shm_openmmap創建進程共享 信號量。

  • 混合fork和線程通常不是一項簡單的任務,你應該在做之前真正考慮三次。
+0

+1不混合pthread_create()和fork()。當我專注於初始化問題時,我完全錯過了。這就是說,如果他們在提問者的目標平臺上,我認爲使用信號量是合理的。另外,您可以傳遞'1'作爲sem_init()'的第二個參數,以使它們跨進程共享。 –

+0

@BenKelly,作爲一個側面說,它是'0'可以共享。但那不是重點,如果你分叉,它們可能是可共享的,但它們是分叉之後的兩個不同的對象。兩個進程在相同的地址看到它們,但是指向不同的野獸。 –

+0

對不起,你是正確的。我閱讀了文檔的第一部分,「如果pshared非零,那麼信號量在進程之間共享,」但錯過了這一部分:「並且應該位於共享內存區域中(請參見shm_open(3),mmap(2 )和shmget(2))。「對不起,我的困惑! –