2

我有这个过程图。在每个线程中都开始新进程。首先是进程 1,当它结束时会发布信号,下一个可能的进程是 2 和 4。
此图解释更多:1:http: //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);

} 
4

2 回答 2

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);
于 2012-12-03T20:19:37.407 回答
2

本的回答向您展示了您的主要问题,但您还有其他问题。您正在轻松地使用线程、进程和信号量进行编程。

  • 信号量不能这样编程。所有信号量函数都给出错误返回码是有充分理由的。例如sem_wait ,如果进程接收到信号,可能会遇到“虚假唤醒”。所以你必须检查返回然后errno看看发生了什么,在编程 POSIX 信号量时没有办法解决这个问题。

  • 信号量只是 POSIX 中的一个可选功能。从一开始就设计的 POSIX 功能开始可能更容易,即pthread_mutex_tpthread_cond_t. 您作为补充获得的是便携性。仍然有一些非常常见的架构不完全支持信号量。

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

    父级的整个虚拟地址空间在子级中复制

    这意味着child中的信号量是一个副本,两个进程将无法通过它进行通信。您必须使用类似的东西shm_openmmap创建进程共享信号量。

  • 混合fork和线程通常不是一项微不足道的任务,在这样做之前你真的应该三思而后行。
于 2012-12-03T21:15:17.353 回答