2011-06-21 67 views
0

我试图做一些基本的并行处理,使用POSIX共享内存段和未命名的信号对整数进行奇偶排序。我几乎所有的工作都在这一点上,除了最后一件事情:如果我没有直接在信号量锁定/解锁后执行perror(),代码的行为将会有所不同(并且随后会错误排序)。如果我在信号量锁定之后直接离开perror()调用并且解锁,代码完美地对整数数组进行排序。perror()调用影响信号量锁定/解锁的问题

int semaphoreCheck = sem_init(&(sharedData->swapSem), 1, 1); 

if (semaphoreCheck == -1) 
{ 
    perror("failed to initialize semaphore"); 
    exit(EXIT_FAILURE); 
} 

pid_t fork1; 
fork1 = fork(); 
if (fork1 == 0) 
{ 
    // original.child 
    pid_t fork2; 
    fork2 = fork(); 
    if (fork2 == 0) 
    { 
     // child.child 
     // do a portion of the sort here 
     while(sharedData->evenSwap || sharedData->oddSwap) 
     { 
      // obtain lock on the shared vector 
      // int commandCheck = shmctl(sharedID, SHM_LOCK, NULL); 
      int commandCheck = sem_wait(&(sharedData->swapSem)); 
      perror("semaphore lock"); 
      // if lock was obtained 
      if (commandCheck == 0) 
      { 
       sharedData->evenSwap = false; 
       for(int index = 1; index < arraySize - 1; index +=2) 
       { 
        if(sharedData->vecData[index] > sharedData->vecData[index + 1]) 
        { 
         int temp; 
         temp = sharedData->vecData[index]; 
         sharedData->vecData[index] = sharedData->vecData[index+1]; 
         sharedData->vecData[index+1] = temp; 
         sharedData->evenSwap = true; 
        }  
       } 
       // release lock on the shared vector 
       commandCheck = sem_post(&(sharedData->swapSem)); 
       perror("semaphore unlock"); 
       if (commandCheck == -1) 
       { 
        perror("failed to unlock shared semaphore"); 
       } 
      } 
      else perror("failed to lock shared semaphore"); 
     } 
     _exit(0); 
    } 
    else if (fork2 > 0) 
    { 
     // child.parent 
     // do a portion of the sort here 
     while(sharedData->evenSwap || sharedData->oddSwap) 
     { 
      // obtain lock on the shared vector 
      int commandCheck = sem_wait(&(sharedData->swapSem)); 
      perror("semaphore lock"); 
      // if lock was obtained 
      if (commandCheck == 0) 
      { 
       sharedData->oddSwap = false; 
       for(int index = 0; index < arraySize - 1; index +=2) 
       { 
        if(sharedData->vecData[index] > sharedData->vecData[index + 1]) 
        { 
         int temp; 
         temp = sharedData->vecData[index]; 
         sharedData->vecData[index] = sharedData->vecData[index+1]; 
         sharedData->vecData[index+1] = temp; 
         sharedData->oddSwap = true; 
        }  
       } 
       // release lock on the shared vector 
       commandCheck = sem_post(&(sharedData->swapSem)); 
       perror("semaphore unlock"); 
       if (commandCheck == -1) 
       { 
        perror("failed to unlock shared semaphore"); 
       } 
      } 
      else perror("failed to lock shared semaphore"); 
     } 
     _exit(0); 
    } 
    else 
    { 
     // child.error 
     // forking error. 
     perror("failed to fork in child"); 
     exit(EXIT_FAILURE); 
    } 
} 
else if(fork1 > 0) 
{ 
    // original.parent 
    // wait for the child process to finish. 
    waitpid(fork1, NULL, 0); 

} 
else 
{ 
    // forking error 
    perror("failed to fork"); 
    exit(EXIT_FAILURE); 
} 

我只能猜测,这与如何信号量块的过程中,如果等待不能被满足的事,但我不明白PERROR()调用如何解决它。

+2

多线程可能很奇怪,如果你有一个错误perror可能会改变线程的时机给你正确的输出。作为一个方面说明,如果您使用的是C++,而您的问题使用boost线程库进行标记,这真的会简化一些事情。我建议你使用它。 – GWW

回答

0

我认为你的问题可能与你的方式有关(不)在你得到信号后检查条件仍然适用,或者检查条件本身是错误的。

您有:

while(sharedData->evenSwap || sharedData->oddSwap) 
    { 
     // obtain lock on the shared vector 
     int commandCheck = sem_wait(&(sharedData->swapSem)); 
     perror("semaphore lock"); 
     // if lock was obtained 
     if (commandCheck == 0) 
     { 
      sharedData->oddSwap = false; 

后你得到的信号,你应该验证,要么sharedData->evenSwapsharedData->oddSwap仍然是真实的,放弃的信号如果没有。这是一个标准的习惯用法;你检查,锁定并重新检查,因为状态可能在原始检查和获得锁定之间发生了变化。

在此假设下,perror()调用会更改进程的时间,允许条件保持不变的时间比不存在perror()调用的时间更长。所以,这里有个时间问题。