2012-12-03 31 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))。“对不起,我的困惑! –