0

我正在尝试编写一个练习,C Linux其中我有一个带有 2 个点的信号量和由参数输入的“n”个进程。我需要前 2 个进程使用信号量使用 2 个点,每个 5 秒,然后将信号量留给其他剩余进程来做他们的事情。问题是并非所有其他进程都等待信号量空闲,其中一些显示信号量错误(查看底部的结果)。我相信问题在于等待子进程,因为我有一个waitipid和一个wait函数,但我需要如果信号量中有一个空闲点,任何运行的子进程都可以使用它。这是代码:

//gcc SemaphoreExample.c -o s
//./s 5

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/sem.h>

void semaphoreTask(int semid, int semnum, int semBusy)
{
    struct sembuf data;
    data.sem_num = semnum;
    data.sem_flg = 0;
    data.sem_op = semBusy;

    if(semop(semid,&data,1) == -1)
    {
        printf("\nSemaphore Error\n");
        exit(-1);
    }
}

int main(int argc, char *argv[])
{
    int i, fdSemaphore, quantity, fdsemctl, j;
    pid_t pid[15];

    system("clear");

    if(argc-1 < 1)
    {
        printf("Some arguments are missing\n");
        return EXIT_FAILURE;
    }

    printf("Number of arguments entered:\n\nargc: %d\n\nValues from the arguments:\n\n",argc-1);

    for(i=0;i<argc;i++)
    {
        printf("argv[%d]: %s\n",i,argv[i]);
    }

    printf("\n\n");

    fdSemaphore = semget(1234,1,IPC_CREAT|0777);

    if(fdSemaphore == -1)
    {
        printf("\nError creating the Semaphore\n");
        return EXIT_FAILURE;
    }

    fdsemctl = semctl(fdSemaphore,0,SETVAL,2);

    if(fdsemctl == -1)
    {
        printf("\nError opening the Semaphore\n");
        return EXIT_FAILURE;
    }

    quantity = atoi(argv[1]);

    for(i=0;i<quantity;i++)
    {
        pid[i] = fork();

        if(pid[i] == -1)
        {
            printf("\nError creating the Child Process\n");
            return EXIT_FAILURE;
        }

        if(pid[i] == 0)
        {
            semaphoreTask(fdSemaphore,0,-1);
            printf("\n[%d] I go to sleep\n",getpid());
            sleep(5);
            printf("\n[%d] I wake up\n",getpid());
            semaphoreTask(fdSemaphore,0,1);
        }
        else
        {
            //printf("\nJust wait\n");
            waitpid(pid[i],NULL,WNOHANG);
        }
    }

    for(j=0;j<quantity;j++)
    {
        wait(NULL);
    }

    semctl(fdSemaphore,0,IPC_RMID);

    return EXIT_SUCCESS;
}

这是我得到的结果:

Result:

Number of arguments entered:

argc: 1

Values from the arguments:

argv[0]: ./s
argv[1]: 5


[2845] I go to sleep

[2844] I go to sleep

[2845] I wake up

[2844] I wake up

Semaphore Error

[2843] I go to sleep

Semaphore Error

Semaphore Error

[2843] I wake up

Semaphore Error

我应该使用wait还是waitpid只使用?

4

2 回答 2

1

问题是信号量被分叉的孩子删除了。

线后

semaphoreTask(fdSemaphore,0,1);

添加

exit(0);
于 2013-10-05T06:56:20.123 回答
0

如果你使用 sem_post 和 sem_wait 调用,实现你想要的会简单得多。我在一个 OpenBSD 系统上,我假设 Linux 也有同样的东西。

于 2013-10-04T23:53:54.573 回答