Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 内存映射文件_C_Unix_Mmap_Memory Mapped Files - Fatal编程技术网

C 内存映射文件

C 内存映射文件,c,unix,mmap,memory-mapped-files,C,Unix,Mmap,Memory Mapped Files,我编写了一段代码,用于将内容写入映射的缓冲区,该缓冲区通过使用mmap()系统调用进行映射。 在映射的缓冲区中做了一些更改之后,我调用了msync()。它应该会更新到磁盘上的文件 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include <sys/types.h> #include <sys/stat.h> #in

我编写了一段代码,用于将内容写入映射的缓冲区,该缓冲区通过使用mmap()系统调用进行映射。 在映射的缓冲区中做了一些更改之后,我调用了msync()。它应该会更新到磁盘上的文件

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h> 
#include <sys/types.h>
#include <sys/stat.h>
#include<sys/mman.h>
#include<fcntl.h>
#define FILEMODE S_IRWXU | S_IRGRP | S_IROTH
#define MAX 150

main(int argc,char *argv[])
{
int fd,ret,len;
long int len_file;
struct stat st;
char *addr;
char buf[MAX];


if(argc > 1)
{
    if((fd = open(argv[1],O_RDWR | O_APPEND | O_CREAT ,FILEMODE)) < 0)
        perror("Error in file opening");

    if((ret=fstat(fd,&st)) < 0)
        perror("Error in fstat");

    len_file = st.st_size;

           /*len_file having the total length of the file(fd).*/


    if((addr=mmap(NULL,len_file,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0)) == MAP_FAILED)
        perror("Error in mmap");

    len = len_file; 

    while((fgets(buf,MAX,stdin)) != NULL)
    {
        strcat(addr+len,buf);
        printf( "Val:%s\n",addr ) ; //Checking purpose
        len = len + (strlen(buf));
    }
    if((msync(addr,len,MS_SYNC)) < 0)
        perror("Error in msync");

    if( munmap(addr,len) == -1)
        printf("Error:\n");
    printf("addr %p\n",addr);
}
else
{
    printf("Usage a.out <filename>\n");
}
}
但是,它没有对磁盘上的文件进行任何更改

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h> 
#include <sys/types.h>
#include <sys/stat.h>
#include<sys/mman.h>
#include<fcntl.h>
#define FILEMODE S_IRWXU | S_IRGRP | S_IROTH
#define MAX 150

main(int argc,char *argv[])
{
int fd,ret,len;
long int len_file;
struct stat st;
char *addr;
char buf[MAX];


if(argc > 1)
{
    if((fd = open(argv[1],O_RDWR | O_APPEND | O_CREAT ,FILEMODE)) < 0)
        perror("Error in file opening");

    if((ret=fstat(fd,&st)) < 0)
        perror("Error in fstat");

    len_file = st.st_size;

           /*len_file having the total length of the file(fd).*/


    if((addr=mmap(NULL,len_file,PROT_READ|PROT_WRITE,MAP_PRIVATE,fd,0)) == MAP_FAILED)
        perror("Error in mmap");

    len = len_file; 

    while((fgets(buf,MAX,stdin)) != NULL)
    {
        strcat(addr+len,buf);
        printf( "Val:%s\n",addr ) ; //Checking purpose
        len = len + (strlen(buf));
    }
    if((msync(addr,len,MS_SYNC)) < 0)
        perror("Error in msync");

    if( munmap(addr,len) == -1)
        printf("Error:\n");
    printf("addr %p\n",addr);
}
else
{
    printf("Usage a.out <filename>\n");
}
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义文件模式S|u IRWXU | S|u IRGRP | S|IROTH
#定义最大值150
main(int argc,char*argv[])
{
内部fd、ret、len;
长int len_文件;
结构统计;
char*addr;
char buf[MAX];
如果(argc>1)
{
if((fd=open(argv[1],O|RDWR | O|u APPEND | O|u CREAT,FILEMODE))<0)
perror(“文件打开错误”);
如果((ret=fstat(fd,&st))<0)
perror(“fstat中的错误”);
len_file=st.st_size;
/*具有文件总长度(fd)的len_文件*/
if((addr=mmap(NULL,len_文件,PROT_读取| PROT_写入,MAP_私有,fd,0))==MAP_失败)
perror(“mmap中的错误”);
len=len_文件;
while((fgets(buf,MAX,stdin))!=NULL)
{
strcat(addr+len,buf);
printf(“Val:%s\n”,addr);//检查目的
len=len+(strlen(buf));
}
if((msync(addr,len,MS_SYNC))<0)
perror(“msync中的错误”);
if(munmap(addr,len)=-1)
printf(“错误:\n”);
printf(“地址%p\n”,地址);
}
其他的
{
printf(“用法a.out\n”);
}
}

如果希望更改反映在磁盘文件中,则必须将文件映射为
map\u SHARED
,而不是
map\u PRIVATE

此外,不能仅通过在映射末尾之外写入来扩展文件。必须使用
ftruncate()
将文件扩展到新大小,然后更改映射以包含文件的新部分。更改映射的可移植方法是取消映射,然后使用新大小重新创建映射;在Linux上,您可以使用
mremap()

您的
len
len\u文件
变量的类型应该是
size\u t
,您应该使用
memcpy()
而不是
strcat()
,因为您确切地知道字符串的长度,确切地知道要复制它的位置,并且不想复制空终止符

以下代码修改在Linux上工作(使用
mremap()
):

定义GNU源
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义文件模式S|u IRWXU | S|u IRGRP | S|IROTH
#定义最大值150
int main(int argc,char*argv[])
{
int fd,ret;
文件大小,len;
结构统计;
char*addr;
char buf[MAX];
如果(argc<2)
{
printf(“用法a.out\n”);
返回退出失败;
}
如果((fd=open(argv[1],O|u RDWR | O|u CREAT,FILEMODE))<0)
{
perror(“文件打开错误”);
返回退出失败;
}
如果((ret=fstat(fd,&st))<0)
{
perror(“fstat中的错误”);
返回退出失败;
}
len_file=st.st_size;
/*具有文件总长度(fd)的len_文件*/
if((addr=mmap(NULL,len_文件,PROT_读取| PROT_写入,MAP_共享,fd,0))==MAP_失败)
{
perror(“mmap中的错误”);
返回退出失败;
}
while((fgets(buf,MAX,stdin))!=NULL)
{
len=len_文件;
len_文件+=strlen(buf);
如果(ftruncate(fd,len_文件)!=0)
{
perror(“错误扩展文件”);
返回退出失败;
}
if((addr=mremap(addr,len,len_文件,mremap_可能移动))==MAP_失败)
{
perror(“错误扩展映射”);
返回退出失败;
}
memcpy(addr+len,buf,len_文件-len);
printf(“Val:%s\n”,addr);//检查目的
}
if((msync(addr,len,MS_SYNC))<0)
perror(“msync中的错误”);
if(munmap(addr,len)=-1)
perror(“munmap中的错误”);
如果(关闭(fd))
perror(“关闭错误”);
返回0;
}

请注意,您为文件提供了一个与文件大小完全相同的映射。如果在调用
open(2)
时创建该文件,它的长度将为
0
,如果内核不从
0
长度映射设置任何类型的内存映射,我也不会感到惊讶。(可能是吗?我从来没有试过…)

我建议在执行映射之前使用
ftruncate(2)
扩展文件的长度。(请注意,使用
ftruncate(2)
扩展文件不是很好移植;并非所有平台都提供扩展功能,也并非所有文件系统驱动程序都支持扩展功能。有关详细信息,请参阅系统手册页。)

您必须使用
MAP\u共享的
映射才能将文件修改保存到磁盘

你对perror(3)
的使用不太正确
perror(3)
不会终止您的程序,因此它将继续执行错误的假设:

if((ret=fstat(fd,&st)) < 0)
    perror("Error in fstat");
if((ret=fstat(fd,&st))<0)
perror(“fstat中的错误”);
应改为:

if((ret=fstat(fd,&st)) < 0) {
    perror("Error in fstat");
    exit(1);
}
if((ret=fstat(fd,&st))<0){
perror(“fstat中的错误”);
出口(1);
}
(或者
exit(exit\u FAILURE)
如果你想更具可移植性——我觉得这对眼睛来说有点难,但我生活在Linux世界。)

strcat(3)
希望在
dest
字符串的末尾找到一个ASCII NUL字符(字节值
0x00
,C表示法
'\0'
)——通常的C字符串结尾标记。如果您在这个程序中创建一个ASCII NUL,那么您的文件将不会包含它——毕竟它的长度是零——我不知道通过
mmap(2)
读取零字节文件的后果。如果文件已经存在并且包含数据,则文件中可能没有编码ASCII NUL
strcat(3)
几乎肯定是写入文件的错误工具。(无论如何,没有人想在他们的文件中使用ASCII NUL。)请尝试使用
memcpy(3)

来自匿名评论