无法访问共享内存
我正在处理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个字节等。
当试图访问缓冲区我得到一个分段错误。
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
文件这个文件,以确保申报为A
和B
之间是一致的。用我上面张贴的解决方案,应用程序将与文件大小> 1024,您需要相应地处理这个问题,以确保不超过缓冲区大小崩溃。
为什么心不是它具有指针工作
可以从主进程不访问(非共享)存储器在从属进程,特别是不被简单地传递指针通过共享内存(这会使共享内存概念过时)。你在你的主进程与malloc()
分配的内存不是共享内存段的一部分,所以它不是从从属进程访问。
此外,mmap()
,默认情况下,不能保证在这两个过程返回相同的虚拟地址。所以,即使当传递指向内部在主共享存储器段中的位置一个指针,它不指向所述从属进程内的任何地方是有用的,除非你传递特定参数来mmap()
。有关更多详细信息,请参见mmap(2)。
如果你需要存储在SHM指针然后再打存储从SHM开始偏移。当然,在这种情况下,目标是指向SHM。 – SparKot 2013-03-27 09:00:46
@Sparkot:我无法“从SHM开始存储偏移量”。你能解释一下吗? – Angus 2013-03-27 09:19:29
你在哪里分配'buffer'?在堆上? – SparKot 2013-03-27 09:21:10