1

我创建了一个程序,通过作为参数传递的 shmid(共享内存 id)显示共享内存段信息。

将数据与命令 ipcs 返回的数据进行比较,很明显我的程序显示了一些关于共享内存段的错误信息。

你能帮我理解为什么吗?

谢谢你。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <time.h>
#include <errno.h>

struct shmem_info {
    int id;
    struct shmid_ds data;
};

int *allocate_int(int n) {
    int *mem;

    if((mem=malloc(n*sizeof(int)))==NULL) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }

    return mem;
}

struct shmem_info *allocate_shminfo(int n) {
    struct shmem_info *mem;

    if((mem=malloc(n*sizeof(struct shmem_info)))==NULL) {
        perror("malloc");
        exit(EXIT_FAILURE);
    }

    return mem;
}

int parse_int(char *str) {
    int n;

    n=atoi(str);

    return n;
}

int open_fileRW(char *path) {
    int fd;

    if((fd=open(path,O_RDWR|O_CREAT,0666))==-1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    return fd;
}

void close_file(int fd) {

    if(close(fd)==-1) {
        perror("close");
        exit(EXIT_FAILURE);
    }
}

struct shmid_ds get_shminfo(int id) {
    struct shmid_ds data;

    errno=0;

    if(shmctl(id,IPC_STAT,&data)==-1) {
        switch(errno) {
            case EACCES:
                fprintf(stderr,"Shmid %d: read acces not allowed\n", id);
                exit(EXIT_FAILURE);

            case EINVAL:
                fprintf(stderr,"Shmid %d: invalid shmid\n", id);
                exit(EXIT_FAILURE);

            default:
                perror("shmctl");
                exit(EXIT_FAILURE);
                break;
        }
    }

    return data;
}

void write_shminfo(int fd, struct shmem_info shmi) {
    ssize_t w, tot=0, size=sizeof(struct shmem_info);

    for(;;) {
        errno=0;

        w=write(fd,&shmi,size-tot);

        if(w==-1 && errno!=EINTR) {
            perror("write");
            exit(EXIT_FAILURE);
        }

        if(w==0) return;

        tot+=w;
    }
}

struct shmem_info read_shminfo(int fd) {
    ssize_t r, tot=0, size=sizeof(struct shmem_info);
    struct shmem_info shmi;

    for(;;) {
        errno=0;

        r=read(fd,&shmi,size-tot);

        if(r==-1 && errno!=EINTR) {
            perror("write");
            exit(EXIT_FAILURE);
        }

        if(r==0) return shmi;

        tot+=r;
    }
}

void print_shminfo(FILE *out, struct shmem_info shmi) {
    fprintf(out,"Shmid: %d\n", shmi.id);
    fprintf(out,"Size of segment (bytes): %d\n", (int)shmi.data.shm_segsz);
    fprintf(out,"PID of creator: %d\n", (int)shmi.data.shm_cpid);
    fprintf(out,"No. of current attaches: %d\n", (int)shmi.data.shm_nattch);
    fprintf(out,"Last attach time: %ld\n", shmi.data.shm_atime);
    fprintf(out,"Last detach time: %ld\n", shmi.data.shm_dtime);
    fprintf(out,"Last change time: %ld\n", shmi.data.shm_ctime);
    fprintf(out,"PID of last shmat/shmdt: %d\n", (int)shmi.data.shm_lpid);
    fprintf(out,"Key supplied to shmget(2): %d\n", (int)shmi.data.shm_perm.__key);
    fprintf(out,"Effective UID of owner: %d\n", (int)shmi.data.shm_perm.uid);
    fprintf(out,"Effective GID of owner: %d\n", (int)shmi.data.shm_perm.gid);
    fprintf(out,"Effective UID of creator: %d\n", (int)shmi.data.shm_perm.cuid);
    fprintf(out,"Effective GID of creator: %d\n", (int)shmi.data.shm_perm.cgid);
    fprintf(out,"Permissions + SHM_DEST and ESHM_LOCKED flag: %hd\n", shmi.data.shm_perm.mode);
    fprintf(out,"Sequence number: %hd\n", shmi.data.shm_perm.__seq);
    fprintf(out,"\n");
}

int main(int argc, char *argv[]) {
    int fd, n, i;
    struct shmem_info *shmi;

    if(argc<2) {
        fprintf(stderr,"Usage: %s <shmid> <shmid> ... <shmid>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    n=argc-1;

    argv=argv+1;

    shmi=allocate_shminfo(n);

    for(i=0;i<n;i++) {
        shmi[i].id=parse_int(argv[i]);
    }

    for(i=0;i<n;i++) {
        shmi[i].data=get_shminfo(shmi[i].id);
    }

    fd=open_fileRW("shmid_info-log.txt");

    for(i=0;i<n;i++) {
        write_shminfo(fd,shmi[i]);
    }

    for(i=0;i<n;i++) {
        shmi[i]=read_shminfo(fd);
    }

    for(i=0;i<n;i++) {
        print_shminfo(stdout,shmi[i]);
    }

    close_file(fd);

    free(shmi);

    exit(EXIT_SUCCESS);
}
4

1 回答 1

0

是你的read_shminfo功能有问题。它适用于本地 shmi,而不是处理使用 shmi=allocate_shminfo(n); 分配的 shmi

一种修复方法:

void read_shminfo(int fd, struct shmem_info *shmi) {
//    struct shmem_info shmi;
    ssize_t r, tot=0, size=sizeof(struct shmem_info);

    for(;;) {
        errno=0;

        r=read(fd,(void *)&shmi,size-tot);

        if(r==-1 && errno!=EINTR) {
            perror("write");
            exit(EXIT_FAILURE);
        }

        if(r==0)
                return ;

        tot+=r;
    }
}

主要是:

for(i=0;i<n;i++) {
    read_shminfo(fd,&shmi[i]);
}
于 2012-08-30T15:35:03.487 回答