perror() 调用影响信号量锁定/解锁的问题

发布于 2024-11-16 06:47:53 字数 3844 浏览 2 评论 0原文

我正在尝试使用 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() 调用如何修复它。

I'm trying to do some basic parallel processing to do an odd-even sort on integers using POSIX shared memory segments and unnamed semaphores. I have pretty much everything working at this point, except for one final thing: if I do not perror() directly after semaphore locks/unlocks the code acts differently (and subsequently sorts incorrectly). If I leave the perror() calls directly after semaphore locks and unlocks in, the code sorts the array of integers perfectly.

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

I can only guess that this has to do with how the semaphore blocks the process if a wait cannot be fulfilled, but I do not understand how perror() calls fix it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

Oo萌小芽oO 2024-11-23 06:47:53

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

您有:

    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 是否仍然为 true,如果不是,则放弃信号量。这是一个标准的习语;您检查、锁定并重新检查,因为在原始检查和获得锁定之间状态可能已发生变化。

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

I think your problem may be related to the way you are (not) checking that the conditions still apply after you get the semaphore, or that the checking conditions are themselves wrong.

You have:

    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;

After you get the semaphore, you should probably validate that either sharedData->evenSwap or sharedData->oddSwap is still true, relinquishing the semaphore if not. This is a standard idiom; you check, lock and recheck, because the status may have changed between the original check and the time you gain the lock.

Under this hypothesis, the perror() calls alter the timing of the processes, allowing the conditions to stay unchanged for longer than when the perror() calls are not present. So, there is a timing problem here, somewhere.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文