使用后如何正确删除信号量?

How to properly remove semaphores after usage?

我正在使用大量信号量来同步对共享内存的多进程访问。

我通过

初始化信号量
int scount = 80000;
int semid = semget(IPC_PRIVATE, scount, 0666 | IPC_CREAT);

效果很好。

在程序结束时,我删除了通过

设置的信号量
semctl(semid, 0, IPC_RMID);

但是,当我通过

检查系统中的信号量时
ipcs -S 

在控制台中,我看到它们还在那里。

seminfo:
    semmap:     30  (# of entries in semaphore map)
    semmni:      8  (# of semaphore identifiers)
    semmns:  80064  (# of semaphores in system)       <------ ????
    semmnu:      0  (# of undo structures in system)
    semmsl:  87381  (max # of semaphores per id)
    semopm:      5  (max # of operations per semop call)
    semume:     10  (max # of undo entries per process)
    semusz:     32  (size in bytes of undo structure)
    semvmx:  32767  (semaphore maximum value)
    semaem:  16384  (adjust on exit max value)

我还尝试通过

在控制台中手动删除它们
ipcrm -s [semid]

这似乎可以很好地删除设置(即 semid 在命令之前的 ipcs -s 中列出并在命令之后消失)。然而 ipcs -S 仍然显示

semmns:  80064  (# of semaphores in system)

如何在使用后正确清理信号量,使它们不再出现在"semmns: .... (# of semaphores in system)"中?

我问的原因是,如果没有正确清理信号量,我的下一个 运行 程序将无法运行,因为打开信号量的数量将超过限制。我需要重新启动才能将其重置为 0。

PS:我在 Mac OS,但也希望它在 Linux.

上工作

semget 不会 return 错误。当我通过以下方式初始化信号量集时,下一步发生错误:

semun_t semun = {.val = 1}; // initial semaphore value => 1 = released
for (int i=0; i<scount; i++){
        if(semctl(semid, i, SETVAL, semun) == -1) {perror("semctl init");exit(1);}
    }

我得到的错误是:

semctl init: Invalid argument

遇到同样问题的朋友:

ipcs -S调用时semmns下显示的数字是目前已经使用的信号灯数量。这确实 not 意味着它们仍在使用中。所以即使你正确地删除了一个信号量,计数器 semmns 也不会减少。

并且 semctl init: Invalid argument 错误来自于对集合中的信号灯数量使用了太大的值。