2013-10-04 19 views
0

我试图在C Linux中编写一个练习,其中我有一个信号量,带有2个点和通过参数输入的“n”个进程。我需要前2个进程使用信号量,每个信号量使用2个点,每个5秒,然后为剩下的其他进程留下信号量来完成它们的工作。问题在于并非所有其他进程都等待信号量释放,其中一些进程显示信号量错误(请查看底部的结果)。我相信问题在于等待子进程,因为我有一个waitipidwait函数,但是如果在信号量中有一个空闲点,那么任何运行的子进程都可以使用它。下面的代码:等待使用信号量时的分叉过程

//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

回答

0

如果您使用sem_post和sem_wait调用,实现您想要的更简单。我在一个OpenBSD系统上,我假设Linux具有相同的功能。

+2

我相信大部分人都同意,POSIX信号更容易处理比SYSV信号量,但是这不是一个真正的答案。 – Duck

1

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

线

semaphoreTask(fdSemaphore,0,1); 

后添加

exit(0);