2013-03-27 126 views
1

我正在處理mmap和共享內存上的示例程序。這裏是一段代碼,我試圖,無法訪問共享內存

方法B

#include<stdio.h> 
#include<sys/mman.h> 
#include<fcntl.h> 
#include<unistd.h> 
#include<malloc.h> 

typedef struct sh_mem_t{ 
int offset; 
char *buffer; 
}sh_mem; 

int main(){ 
int fd; 
sh_mem *shm_obj; 

fd = shm_open("/myshm",O_RDWR,0777); 
if(fd == -1){ 
    perror("fd:ERROR"); 
    return -1; 
} 

shm_obj = mmap(0,sizeof(sh_mem),PROT_READ | PROT_WRITE,MAP_SHARED,fd,0); 
if(shm_obj == MAP_FAILED){ 
    perror("shm_obj:ERROR"); 
    return -1; 
} 

printf("\n offset : %d \n",shm_obj->offset); 
// printf("\n Good work! : %s \n",shm_obj->buffer); 

return 0; 
} 

方法A

#include<stdio.h> 
#include<unistd.h> 
#include<fcntl.h> 
#include<malloc.h> 
#include<string.h> 
#include<stdlib.h> 
#include<sys/mman.h> 
#include<sys/sem.h> 

typedef struct sh_mem_t{ 
    int offset; 
    char *buffer; 
}sh_mem; 

int main(int argc,char *argv[]){ 
    int file_size = 0; 
    int fd_sh = 0; 
    sh_mem *shmptr = NULL; 
    int fd = 0; 
    char offset[2]; 
    int no_bytes_read = 0; 
    int read_size = 10; 
    int count = 0; 
    int ret_val = 0; 

    /* Variables for semaphore */ 
    int ret = 0; 
    int semid = 0; 
    key_t sem_key = 0; 
    struct sembuf op[1]; 

    union semun{ 
    int val; 
    struct semid_ds *buf; 
    unsigned short *array; 
    }; 
    union semun arg; 

    /* Validate the i/p parameters */ 
    if(argc < 3){ 
    perror("argc:Did u forget the I/P file and the count 0?"); 
    return -1; 
    } 
    printf("File : %s",argv[1]); 

    count = atoi(argv[2]); 

    /* Create a semaphore */ 
    semid = semget(sem_key,1,IPC_CREAT | 0777); 
    if(semid == -1){ 
    perror("semid:"); 
    return -1; 
    } 
    arg.val = 1; 
    ret = semctl(semid,0,SETVAL,arg); 

    /* Open the file to read the contents */ 
    fd = open(argv[1],O_RDONLY); 

    /* Calculate the total size of the file */ 
    file_size = lseek(fd,0,SEEK_END); 
    lseek(fd,0,SEEK_SET); 
    printf("\n File Size is : %d \n",file_size); 

    /* Create a new memory object */ 
    fd_sh = shm_open("/myshm",O_RDWR | O_CREAT,0777); 

    /* Set the memory object's size */ 
    if((ftruncate(fd_sh,sizeof(sh_mem))) == -1){ 
    perror("ftruncate:ERROR"); 
    return -1; 
    } 

    /* Map the Memory object */ 
shmptr = mmap(0,sizeof(sh_mem),PROT_READ | PROT_WRITE,MAP_SHARED,fd_sh,0); 

    /* Allocate the memory for the buffer */ 
    shmptr->buffer = malloc((sizeof(char)*file_size)); 

    printf("\nThe Map address is : 0x%08x\n",shmptr); 


/* Copy the contents to the shared memory */ 
    read(fd,&offset,1); 

    if(count == 0){ 
    shmptr->offset = 0; 
    } 


    while(shmptr->offset < file_size){ 

    /* Semaphore section Start */ 
    op[0].sem_num=0; 
    op[0].sem_op=-1; 
    op[0].sem_flg=0; 

    semop(semid,op,1); 
    printf("\n ProcessA Entering! \n"); 

    printf("\n initial offset value : %d \n",shmptr->offset); 

    if(shmptr->offset > 0){ 
    shmptr->buffer = shmptr->buffer + shmptr->offset; 
    ret_val = lseek(fd,shmptr->offset,SEEK_SET); 
    } 

    no_bytes_read = read(fd,shmptr->buffer,read_size); 

    shmptr->offset = (read_size + shmptr->offset); 
    printf("\n offset : %d \n",shmptr->offset); 
    printf("\n contents : %s \n",shmptr->buffer); 

    sleep(10); 

    op[0].sem_op = 1; 
    semop(semid,op,1); 
    printf("\n ProcessA Leaving ! \n"); 
    /* Semapore section End*/ 
    } 

    /* Detach from the shared memory */ 
    shmdt(shmptr); 

    close(fd); 
    close(fd_sh); 

    return 0; 
} 

我有處理A中,已經把數據放到共享存儲器包含結構的值偏移量和緩衝區。進程B想要訪問存儲在共享內存(偏移量,緩衝區)中的內容,但我只能訪問偏移量。當試圖訪問緩衝區時,我遇到了分段錯誤。爲什麼我會遇到seg故障。作爲共享對象被映射到共享存儲器。

方法A將投入10個字節到共享存儲器和將進入睡眠狀態,然後再次它繼續把下一個10個字節等。

+0

如果你需要存儲在SHM指針然後再打存儲從SHM開始偏移。當然,在這種情況下,目標是指向SHM。 – SparKot 2013-03-27 09:00:46

+0

@Sparkot:我無法「從SHM開始存儲偏移量」。你能解釋一下嗎? – Angus 2013-03-27 09:19:29

+0

你在哪裏分配'buffer'?在堆上? – SparKot 2013-03-27 09:21:10

回答

3

當試圖訪問緩衝區我得到一個分段錯誤。

buffer聲明爲pointer作爲映射內存的一部分:

typedef struct sh_mem_t{ 
int offset; 
char *buffer; 
}sh_mem; 

傳輸過程之間的指針是沒有意義的,因爲指針沒有在從屬進程任何意義 - 數據它指向仍然駐留在主進程中。

您需要包括要傳送由主到從屬進程的實際數據:

typedef struct sh_mem_t{ 
int offset; 
char buffer[BUFSIZE]; 
}sh_mem; 

隨着問題的更新的代碼,以下更改是必要的,使其工作:

  • A和B二者,共享存儲器結構的聲明更改爲類似
typedef struct sh_mem_t{ 
    int offset; 
    char buffer[1024]; 
    }sh_mem; 
  • ,取出malloc()shmptr->buffer。也除去其中通過添加偏移量(shmptr->buffer = shmptr->buffer + shmptr->offset;)調整所述緩衝器中的線 - 需要被不同地處理,如果仍需要它

  • ,取消該打印Good work!輸出線。

有了這些變化,我可以開始A過程是怎樣的./A data.txt 0。當我然後啓動B過程,它打印偏移和緩衝的內容,因爲它是最後由A過程打印出來。

一些補充說明

  • 您應該使用頭文件來聲明sh_mem結構,幷包含在這兩個你.c文件這個文件,以確保申報爲AB之間是一致的。

  • 用我上面張貼的解決方案,應用程序將與文件大小> 1024,您需要相應地處理這個問題,以確保不超過緩衝區大小崩潰。


爲什麼心不是它具有指針工作

可以從主進程不訪問(非共享)存儲器在從屬進程,特別是不被簡單地傳遞指針通過共享內存(這會使共享內存概念過時)。你在你的主進程與malloc()分配的內存不是共享內存段的一部分,所以它不是從從屬進程訪問。

此外,mmap(),默認情況下,不能保證在這兩個過程返回相同的虛擬地址。所以,即使當傳遞指向內部在主共享存儲器段中的位置一個指針,它不指向所述從屬進程內的任何地方是有用的,除非你傳遞特定參數來mmap()。有關更多詳細信息,請參見mmap(2)

+0

我嘗試了你上面告訴的,但它不工作。緩衝區正在打印一些垃圾值。 – Angus 2013-03-27 09:20:23

+0

您需要在主進程中初始化它。我會更新我的答案給予一定的暗示 – 2013-03-27 09:21:32

+0

試過,但它也沒有工作 – Angus 2013-03-27 10:00:31