shared memory aufraumen -> falsch oder wie lang brauch Linux dazu?



  • Ich hab ein kleines Programm geschrieben das bis noch nichts macht ausser einen Shared-Memory Bereich anzulegen, sich damit zu verbinden und bei bedarf wieder die Verbidnung zu loeschen.
    Das ganze sieht ungefaehr so aus:

    int main( int argc, char** argv ) 
    {
    	pid_t 	pid 		= getpid();
    	key_t 	key 		= 221283;
    	shm_t 	shmid 		= getshm( key, PAGE_SIZE );
    	char*	shm			= NULL;
    	ssize_t nbytes  	= 0;
    	char 	buffer[BUFSIZ];
    
    	shm = attach_shm( shmid );
    
    	while ( ( nbytes = read( STDIN_FILENO, buffer, MSG_SIZE-1 ) ) != -1 )
    	{
    		if ( strncmp( buffer, MSG_QUIT, strlen( MSG_QUIT ) ) == 0 )
    			break;
    	}
    
    	detach_shm( shm );
    
    	return 0;
    }
    

    und

    int getshm( key_t key, int size )
    {
    	int shmid = -1;
    
    	if ( ( shmid = shmget( key, size, IPC_CREAT | 0660 ) ) == -1 )
    	{
    		error_handler_shmget();
    		exit( EXIT_FAILURE );
    	}
    	return shmid;
    }
    
    char* attach_shm( shm_t shm )
    {
    	char* ptr = shmat( shm, NULL, 0 );
    
    	if ( ptr == (char*)-1 ) 
    	{
    		error_handler_shmat();
    		exit( EXIT_FAILURE );
    	}
    
    	return ptr;
    }
    
    void detach_shm( char* shm )
    {
    	if ( shmdt( shm ) == -1 )
    	{
    		error_handler_shmdt();
    		exit( EXIT_FAILURE );
    	}
    }
    

    Wie ich gelesen habe wird der reservierte Bereich vom Linux-Kernel freigegeben sobald die letzte verbindung geloescht wird.
    Wenn ich das Programm also starte und keine andere Instanz auf den Bereich zugreift muesste der Bereich sofort nach dem Beenden wieder freigegeben werden.

    Hab ich das richtig verstanden?
    Bei mir funktioniert das naehmlich nicht...
    Kann es sein dass der Linux-Kernel dazu eine gewisse Zeit braucht? Habs mal mit ipcs ueberprueft, 5 Minuten nach dem beenden des Programms ist der Bereich aber immer noch existent!

    Mach ich vielleicht etwas falsch oder brauch der Kernel dazu einfach laenger?



  • Hier stehts:

    After a shared memory segment is no longer needed by a process, it should be detached by calling this system call. As mentioned earlier, this is not the same as removing the segment from the kernel! After a detach is successful, the shm_nattch member of the associates shmid_ds structure is decremented by one. When this value reaches zero (0), the kernel will physically remove the segment.

    Das heist wenn nur das Programm auf den Memory-Bereich zugreift und dann sich davon loesst wird der Bereich vom Kernel freigegeben, nur wann, das steht da nicht.



  • Das Problem kommt mir sehr bekannt vor 😉

    Ich nehme jetzt immer meine folgende C-Funktion:

    int detachShm(shmid)
    int shmid;			/*  I:  valid shm id got by previous shmget() */
                                    /* ret: 0 on success */
    				/*      <0 if any error */
    /* procedure releases a shared memory */
    {
    char hstr[STRLGTH];		/* help variable */
    char *cp;			/* help variable */
    int retval;			/* help variable */
    int ret;			/* return variable */
    ret = 0;
    XBUG(DBG_TEST) { fprintf(dbgfile,">>>detachShm(): start, shmid=%d\n",shmid); fflush(dbgfile); }
    if (shmid < 0)
        {
        ret = -10;
        syserror("detachShm(): shmid < 0");
        goto errex;
        }
    cp = (char *) shmat(shmid,NULL,0);
    if (cp != NONE)
        {
        ret = shmdt((void *) cp);
        if (ret < 0)
    	{
    	ret = -20;
    	sprintf(hstr,"detachShm(): shmdt() returns error, errno=%d",errno);
    	warning(hstr);
    	}
        ret = shmctl(shmid,IPC_RMID,NONE);
        if (ret < 0)
    	{
    	ret = -21;
    	sprintf(hstr,"detachShm(): shmctl(%d,IPC_RMID,0) detaching returns error, errno=%d",shmid,errno);
    	warning(hstr);
    	}
        }
    errex:
    XBUG(DBG_TEST) { fprintf(dbgfile,">>>detachShm(): end, ret=%d\n",ret); fflush(dbgfile); }
    return(ret);
    }
    

    Wichtig ist halt der Aufruf "shmctl()". Sollte dann funktionieren (auch auch verschiedenen Unix-Derivaten).
    Wenn das Programm allerdings ohne Freigabe des shm abschmiert, ist das shm weiterhin belegt. Aber das ist ein anderes (oder nächstes) Problem und läßt sich auch lösen 😉


Anmelden zum Antworten