使用信号量时等待分叉进程

时间:2013-10-04 23:41:29

标签: c linux fork wait semaphore

我正在尝试在C Linux中编写一个练习,其中我有一个信号量,其中有两个点,而“n”过程由参数输入。我需要前两个进程使用信号量使用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

2 个答案:

答案 0 :(得分:1)

问题是分叉儿童正在移除信号量。

行后

semaphoreTask(fdSemaphore,0,1);

添加

exit(0);

答案 1 :(得分:0)

如果使用sem_post和sem_wait调用,实现所需的内容要简单得多。我在OpenBSD系统上,我假设Linux有相同的东西。