2013-03-27 113 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