【问题标题】:Problem with perror() calls affecting semaphore locking/unlocking影响信号量锁定/解锁的 perror() 调用问题
【发布时间】:2011-06-21 01:09:06
【问题描述】:

我正在尝试进行一些基本的并行处理,以使用 POSIX 共享内存段和未命名的信号量对整数进行奇偶排序。我现在几乎所有东西都在工作,除了最后一件事:如果我在信号量锁定/解锁之后不直接 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() 调用如何修复它。

【问题讨论】:

  • 多线程可能很奇怪,如果您有错误 perror 可能会更改线程时序以提供正确的输出。附带说明一下,如果您使用的是 c++,您的问题用 boost 线程库标记确实可以简化事情。我建议你使用它。

标签: c++ memory posix semaphore


【解决方案1】:

我认为您的问题可能与您在获得信号量后检查条件是否仍然适用的方式有关,或者检查条件本身是错误的。

你有:

    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-&gt;evenSwapsharedData-&gt;oddSwap 是否仍然为真,如果不是则放弃信号量。这是一个标准的成语;您检查,锁定和重新检查,因为在原始检查和获得锁定之间的状态可能已经改变。

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

【讨论】:

    猜你喜欢
    • 2012-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多