简体   繁体   English

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

[英]semaphores + pthreads, not working properly

I have this graph of process. 我有这个过程图。 In every thread new process begin. 在每个线程中,新过程开始。 First is process 1, when it ends semaphores are posted and next possible process are 2 and 4. 第一个是过程1,在结束时发布信号量,下一个可能的过程是2和4。
This graph explain more : 1 : http://i49.tinypic.com/34t5uo0.png .My script crashes in some times. 该图进一步说明: 1http//i49.tinypic.com/34t5uo0.png。我的脚本有时会崩溃。 Process 1,2, or 4 do not execute. 进程1,2或4不执行。 Where is a problem ? 哪里有问题?

#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);

} 

At least one problem is you spawn the threads before initializing the semaphores: 至少一个问题是在初始化信号量之前生成线程:

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);

This creates a race condition between the main thread initializing the semaphores and the child threads using them. 这在初始化信号量的主线程和使用它们的子线程之间创建了竞争条件。 There is a really good chance of using uninitialized data here. 在这里很有可能使用未初始化的数据。

I recommend swapping the order in your main() function: 我建议在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);

Ben's answer shows you your main problem, but you have others. Ben的答案向您展示了您的主要问题,但还有其他问题。 You are taking programming with threads, processes and semaphores much to easy. 您正在使用线程,进程和信号量进行编程非常容易。

  • Semaphores are not to be programmed like this. 信号量不能像这样编程。 All the semaphore functions give error return codes for a good reason. 所有的信号量函数都有很好的理由提供错误返回代码。 Eg sem_wait may encouter "spurious wakeups" if the process receives a signal. 例如,如果进程接收到信号,则sem_wait可能会诱使“虚假唤醒”。 So you'd have to check the return and then errno to see what happened, there is no way around this when programming POSIX semaphores. 因此,您必须先检查返回值,然后再检查errno以查看发生了什么,在编写POSIX信号量时无法解决此问题。

  • Semaphores are only an optional feature in POSIX. 信号量只是POSIX中的可选功能。 It is probably easier to start with the POSIX features that were designed into it from the beginning, namely pthread_mutex_t and pthread_cond_t . 从一开始就设计成其中的POSIX功能(即pthread_mutex_tpthread_cond_t )可能更容易开始。 What you obtain as a supplement is portability. 您获得的补充是便携性。 There are still very common architectures around that don't fully support semaphores. 周围仍然有很多不完全支持信号量的通用体系结构。

  • The way your are doing this is not the way to share semaphores between processes: 您执行此操作的方式不是在进程之间共享信号量的方式:

    The entire virtual address space of the parent is replicated in the child 父级的整个虚拟地址空间在子级中复制

    which means that the semaphore in the child is a copy, and the two processes will not be able to communicate through it. 这意味着孩子中的信号量是一个副本,并且两个进程将无法通过它进行通信。 You'd have to use something like shm_open and mmap create process shared semaphores. 您必须使用shm_openmmap类的东西来创建进程共享信号量。

  • Mixing fork and threads is usually not a trivial task and you should really think twice before doing that. 混合使用fork和线程通常不是一件容易的事,在这样做之前,您应该三思而后行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM