user3693690
user3693690

Reputation: 133

how to delete shared memory segment after some program failed to detach from it before exit?

i am learning ipc on linux system. After i have tried out several example programs using shared memory, i found some shared memory section pending on my linux system, and they can not be deleted.

i reboot the machine, and they remain.

I write a program trying to delete them, and that does not work too. Because the system thought there was some program still having these shared memory segment attached( See the nattch column).

Does anyone know how to delete them. Thanks.

[root@luaDevelopment 17.2UNIXDomainSocket]# ipcs -m

------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 98304      root       600        393216     2          dest
0x00000000 131073     root       600        393216     2          dest
0x00000000 163842     root       600        393216     2          dest
0x00000000 196611     root       600        393216     2          dest
0x00000000 229380     root       600        393216     2          dest
0x00000000 262149     root       600        393216     2          dest
0x00000000 294918     root       600        393216     2          dest
0x00000000 327687     root       600        393216     2          dest
0x00000000 360456     root       600        393216     2          dest
0x00000000 393225     root       600        393216     2          dest
0x00000000 425994     root       600        393216     2          dest
0x00000000 458763     root       600        393216     2          dest

clearShm.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>

int main(int argc, char *argv[])
{
    int shmIDArray[]={98304,131073,163842,196611,229380,262149,294918,327687,360456,393225,425994,458763};
    for(int i=0; i<sizeof(shmIDArray)/sizeof(int); i++)
    {
        if(shmctl(shmIDArray[i], IPC_RMID, NULL) < 0)
        {
            fprintf(stderr, "remove error for shmid=%d: %s\n", shmIDArray[i], strerror(errno));
        }else{
            printf("delete %d\n", shmIDArray[i]);
        }
    }
    return 0;
}

shell output for the program above

[root@luaDevelopment 17.2UNIXDomainSocket]# ./clearShm
delete 98304
delete 131073
delete 163842
delete 196611
delete 229380
delete 262149
delete 294918
delete 327687
delete 360456
delete 393225
delete 425994
delete 458763

=============================================

Today i start the computer and i find that these shared memory segments are gone. They were still there just before i shut down the computer yesterday. and i don't know why.

Upvotes: 2

Views: 13652

Answers (1)

Pushpendra
Pushpendra

Reputation: 459

Wel first equip your code with below given detail:

You can use int shmctl(int shmid, int cmd, struct shmid_ds *buf); in your code to remove the shared memory segment from the system if in case your program fails or normally exit.

However you should have look at section IPC_RMID of the man page of shmctl. man page state below conditions to be met before you try to remove a shared memory seciton:

IPC_RMID Mark the segment to be destroyed. The segment will only actually be destroyed after the last process detaches it (i.e., when the shm_nattch member of the associated structure shmid_ds is zero). The caller must be the owner or creator, or be privi‐ leged. If a segment has been marked for destruction, then the (nonstandard) SHM_DEST flag of the shm_perm.mode field in the associated data structure retrieved by IPC_STAT will be set.

The caller must ensure that a segment is eventually destroyed; otherwise its pages that were faulted in will remain in memory or swap.

See also the description of /proc/sys/kernel/shm_rmid_forced in proc(5).

You can refer to below code for example:

if(-1 == (shmctl(shmid, IPC_STAT, &shmid_ds)))
{   
    perror("shmctl");
}   

if(-1 == (shmctl(shmid, IPC_RMID, &shmid_ds)))
{   
    perror("shmctl");
}   

To remove existing shared memory segments, its better to use ipcrm -m <shmid> as already told in comments of the question. You can make a shell script which can delete all segments.

Upvotes: 1

Related Questions