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

问题描述

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

我通过初始化信号量

int scount = 80000;
int semid = semget(IPC_PRIVATE,scount,0666 | IPC_CREAT);

效果很好。

在程序结束时,我通过

删除了信号量集。
semctl(semid,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不返回错误。当我通过以下方式初始化信号集时,错误将在下一步发生:

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

解决方法

对于遇到相同问题的人:

semmns调用时在ipcs -S下显示的数字是到目前为止一直在使用的信号灯数量。那不是不是意味着它们仍在使用中。因此,即使您正确删除了信号量,计数器semmns也不会减少。

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