信号量+ pthreads,无法正常工作

时间:2012-12-03 20:09:03

标签: c pthreads semaphore

我有这张流程图。在每个线程中,新进程开始。第一个是流程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);

} 

2 个答案:

答案 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 :(得分:2)

Ben的答案显示了你的主要问题,但你有其他问题。您正在使用线程,进程和信号量进行编程非常简单。

  • 信号量不能像这样编程。所有的信号量 函数提供错误返回代码是有充分理由的。 E.g sem_wait 如果进程接收到信号,则可能包含“虚假唤醒”。所以 你必须检查返回,然后errno看看发生了什么, 在编写POSIX信号量时,没有办法解决这个问题。

  • 信号量只是POSIX中的可选功能。可能是 更容易从设计到它的POSIX功能开始 从一开始,即pthread_mutex_tpthread_cond_t。 您作为补充获得的是便携性。还有很多 围绕它的常见架构并不完全支持信号量。

  • 您这样做的方式是分享信号量的方式 进程之间:

      

    复制父级的整个虚拟地址空间   在孩子身上

    这意味着孩子的信号量是副本,而两者 流程将无法通过它进行通信。你必须这样做 使用shm_openmmap等创建进程共享的内容 信号量。

  • 混合fork和线程通常不是一项微不足道的任务而且你 在做这件事之前应该三思而后行。