2011-06-21 66 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()調用的時間更長。所以,這裏有個時間問題。