C 中的命名信号量在信号处理程序调用后不会被删除

Named semaphores in C are not deleted after a signal handler call

所以下面的代码应该执行以下操作:

  1. 主进程创建 N_READ 数量的 children 进程,然后继续无休止地打印一些行。
  2. children也不停地打印一些行。
  3. 当主进程收到一个 SIGINT 信号(在这种情况下来自终端的 CTRL^C)时,他必须向他的所有 children 发送一个 SIGTERM,等待它们完成,然后删除所有使用的信号量.

命名信号量的使用是合理的,因为这是对 readers-writers 问题的模拟,优先考虑读者。

然而,当我结束程序并再次启动它时,信号量并没有被删除,因为我得到一个 "semaphore already exists" 错误,它们实际上在 /dev/shm.

P.D。这是大学作业,他们说不允许使用全局变量。

在此先感谢您,这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>

#define SEM1 "/example_sem1"
#define SEM2 "/example_sem2"
#define SEM3 "/example_sem3"

#define N_READ 1
#define SECS 0

int  valor_semaforo(sem_t *sem) {
    int sval;

    if (sem_getvalue(sem, &sval) == -1) {
        perror("sem_getvalue");
        sem_unlink(SEM1);
        sem_unlink(SEM2);
        sem_unlink(SEM3);
        exit(EXIT_FAILURE);
    }

   return sval;
}

void manejador_SIGINT(int sig) {

    kill(0,SIGTERM);
    while(wait(NULL)>0);
/*xq no llega xq*/
    sem_unlink(SEM1);
    sem_unlink(SEM2);
    sem_unlink(SEM3);

    exit(EXIT_SUCCESS);
}

int main(void) {
    sem_t *sem_write = NULL,*sem_read = NULL,*sem_count = NULL;
    pid_t pid[N_READ];
    int i;
    struct sigaction act;

    sigemptyset(&(act.sa_mask));
    act.sa_flags = 0;

    act.sa_handler = manejador_SIGINT;
    if (sigaction(SIGINT, &act, NULL) < 0) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }

    if ((sem_write = sem_open(SEM1, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1)) == SEM_FAILED) {
        perror("sem_open");
        exit(EXIT_FAILURE);
    }
    if ((sem_read = sem_open(SEM2, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1)) == SEM_FAILED) {
        perror("sem_open");
        exit(EXIT_FAILURE);
    }
    if ((sem_count = sem_open(SEM3, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) == SEM_FAILED) {
        perror("sem_open");
        exit(EXIT_FAILURE);
    }



    for(i=0;i<N_READ;i++){
        pid[i] = fork();
        if (pid[i] < 0) {
            perror("fork");
            exit(EXIT_FAILURE);
        }
        if (pid[i] == 0) {

            sigemptyset(&(act.sa_mask));
            act.sa_flags = 0;

            act.sa_handler = SIG_IGN;
            if (sigaction(SIGINT, &act, NULL) < 0) {
                perror("sigaction");
                exit(EXIT_FAILURE);
            }
            while(1){

                sem_wait(sem_read);
                sem_post(sem_count);
                if(valor_semaforo(sem_count)==1)
                    sem_wait(sem_write);
                sem_post(sem_read);

                printf("R-INI %d\n",getpid());
                fflush(stdout);
                sleep(SECS);
                printf("R-FIN %d\n",getpid());
                fflush(stdout);


                sem_wait(sem_read);
                sem_wait(sem_count);
                if(valor_semaforo(sem_count)==0)
                    sem_post(sem_write);
                sem_post(sem_read);
            }

        }
    }
        while(1){
            sem_wait(sem_write);
            printf("W-INI %d\n",getpid());
            fflush(stdout);
            sleep(SECS);
            printf("W-FIN %d\n",getpid());
            fflush(stdout);
            sem_post(sem_write);
        }    
    }

正如@Jonathan 所说,我使用的 SIGTERM 信号确实终止了应该清理信号量的进程。通过忽略父进程中的信号,一切正常。