On Sunday, 18 January 2015 at 16:06:39 UTC, tcak wrote:
I create a shared memory by using shmget. And attach to it by using shmat.

Finally, I use shmctl to get statistics to learn number of attachments to that shared memory. According to documentation (linux.die.net/man/2/shmat), number of attachments should be 1.

Same codes, C returns 1, D returns 0. It took me 2 days until realising this.

I put C and D codes, and makefile for quick testing.

Ubuntu 64-bit. Kernel: 3.13.0-44-generic

I checked the shmid_ds at both "core.sys.posix.sys.shm" and "/usr/include/bits/shm.h". They look similar. Although C definition makes a difference based on 32 and 64 bits, D's definition doesn't care about. Because I am on 64-bit kernel, they should be same.



main.c
==========================
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>

void main(){
        // allocate
int id = shmget( IPC_PRIVATE, 4096, IPC_CREAT | S_IRUSR | S_IWUSR );

        // if failed, leave
        if( id == -1 ){
                printf("shmget failed\n");
                return;
        }

        // attach
        void* ptr = shmat( id, 0, 0 );

        // if failed, leave
        if( ptr == (void*)-1 ){
                printf("shmat failed\n");
                shmctl( id, IPC_RMID, 0 );
                return;
        }

        // stat
        struct shmid_ds stat;

        // get statistics
        int res = shmctl( id, IPC_STAT, &stat );
        printf("STAT: %d\n", res);

        // get number of attachments
        printf("NATTCH: %d\n", (unsigned short)stat.shm_nattch);

        // detach
        shmdt( ptr );

        // remove
        shmctl( id, IPC_RMID, 0 );
}


main.d
===============================
import std.stdio;

private import core.sys.posix.sys.mman;
private import core.sys.posix.sys.shm;
private import core.sys.posix.unistd;
private import core.sys.posix.sys.stat;
private static import core.stdc.errno;
private static import core.stdc.time;

void main(){
        // allocate
int id = shmget( IPC_PRIVATE, 4096, IPC_CREAT | S_IRUSR | S_IWUSR );

        // if failed, leave
        if( id == -1 ){
                writeln("shmget failed");
                return;
        }

        // attach
        void* ptr = shmat( id, null, 0 );

        // if failed, leave
        if( ptr == cast(void*)-1 ){
                writeln("shmat failed");
                shmctl( id, IPC_RMID, null );
                return;
        }

        // stat
        shmid_ds stat;

        // get statistics
        int res = shmctl( id, IPC_STAT, &stat );
        writeln("STAT: ", res);

        // get number of attachments
        writeln("NATTCH: ", stat.shm_nattch);

        // detach
        shmdt( ptr );

        // remove
        shmctl( id, IPC_RMID, null );
}



makefile
==============================
all:
        dmd main.d -of"dprog"
        gcc main.c -o cprog

clear:
        rm cprog
        rm dprog


Here is what I did to solve the problem. In D code, I defined my own shmid_ds struct (Structure is taken from /usr/include/bits/shm.h)

// from /usr/include/bits/shm.h
/* Type to count number of attaches.  */
alias shmatt_t = c_ulong;

/* Data structure describing a shared memory segment.  */
version( X86_64 ){
        struct my_shmid_ds{
            ipc_perm shm_perm;          /* operation permission struct */
            size_t shm_segsz;                   /* size of segment in bytes */
            time_t shm_atime;                   /* time of last shmat() */
            time_t shm_dtime;                   /* time of last shmdt() */
            time_t shm_ctime;                   /* time of last change by 
shmctl() */
            pid_t shm_cpid;                     /* pid of creator */
            pid_t shm_lpid;                     /* pid of last shmop */
            shmatt_t shm_nattch;                /* number of current attaches */
            c_ulong __glibc_reserved4;
            c_ulong __glibc_reserved5;
        };
}
else{
        struct my_shmid_ds{
            ipc_perm shm_perm;          /* operation permission struct */
            size_t shm_segsz;                   /* size of segment in bytes */
            time_t shm_atime;                   /* time of last shmat() */
            c_ulong __glibc_reserved1;
            time_t shm_dtime;                   /* time of last shmdt() */
            c_ulong __glibc_reserved2;
            time_t shm_ctime;                   /* time of last change by 
shmctl() */
            c_ulong __glibc_reserved3;
            pid_t shm_cpid;                     /* pid of creator */
            pid_t shm_lpid;                     /* pid of last shmop */
            shmatt_t shm_nattch;                /* number of current attaches */
            c_ulong __glibc_reserved4;
            c_ulong __glibc_reserved5;
        };
}



Then, I changed the type of "stat" variable:

my_shmid_ds stat;



Finally, need to do a casting (Doing this came to me so stupid after writing it in C):

int res = shmctl( id, IPC_STAT, cast( core.sys.posix.sys.shm.shmid_ds* )(&stat) );


After these, it works perfectly. I hope this can be fixed in next version.

Reply via email to