【问题标题】:semaphores + pthreads, not working properly信号量 + pthreads,无法正常工作
【发布时间】:2012-12-03 20:09:02
【问题描述】:

我有这个过程图。在每个线程中都开始新进程。首先是进程 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);

} 

【问题讨论】:

    标签: c pthreads semaphore


    【解决方案1】:

    至少有一个问题是在初始化信号量之前产生线程:

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

    【讨论】:

    • 这仅说明您在代码中遇到的部分问题。我在单独的答案中列出了它们,因为这太长了,无法在评论中列出。
    【解决方案2】:

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

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

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

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

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

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

    • 混合fork 和线程通常不是一个简单的任务,你 在这样做之前真的应该三思而后行。

    【讨论】:

    • +1 表示不混合 pthread_create() 和 fork()。当我专注于初始化问题时,我完全错过了这一点。话虽如此,如果信号量在提问者的目标平台上,我确实认为使用信号量是合理的。此外,您可以将1 传递给sem_init() 的第二个参数,以使它们可跨进程共享。
    • @BenKelly,顺便说一句,0 可以共享。但这不是重点,如果你分叉,它们可能是可共享的,但它们是分叉后的两个不同对象。两个进程在同一个地址看到它们,但引用不同的野兽。
    • 对不起,你是对的。我阅读了文档的第一部分,“如果 pshared 不为零,则信号量在进程之间共享”,但错过了这一部分:“并且应该位于共享内存区域中(参见 shm_open(3)、mmap(2 ) 和 shmget(2))。”对不起,我的困惑!
    猜你喜欢
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 2013-07-09
    • 1970-01-01
    相关资源
    最近更新 更多