如何使用mmap映射空文件

时间:2017-10-23 03:05:33

标签: c linux system-calls mmap

我正在尝试创建一个空文件,如果它不存在。然后使用mmap()映射它,我可以将它传递给我的其他程序进行编写。我不确定mmap的哪些参数适合空文件。我的代码适用于非空文件但如果文件为空则给出错误“无效参数”

代码程序1(如果不存在则只创建一个空文件)

int i;
int fd = open("/home/sungmin/dummy_programs/dummy.txt", O_RDONLY | O_CREAT, 0777);
char *pmap;
pid_t child;

if (fd == -1)
{
    perror("Error opening file for writing");
    exit(EXIT_FAILURE);
}        

struct stat fileInfo = {0};

if (fstat(fd, &fileInfo) == -1)
{
    perror("Error getting the file size");
    exit(EXIT_FAILURE);
}

/*if (fileInfo.st_size == 0)
{
    fprintf(stderr, "Error: File is empty, nothing to do\n");
    exit(EXIT_FAILURE);
}*/

pmap = mmap(0, fileInfo.st_size, PROT_READ | PROT_EXEC  , MAP_ANONYMOUS, fd, 0);
if (pmap == MAP_FAILED)
{
    close(fd);
    perror("Error mmapping the file");
    exit(EXIT_FAILURE);
}

/* Calling fork function */
if((child=fork())==0){

printf("Iam Child process\n\n");
static char *argv[]={"This is some sample text. I need to write this text in my dummy file.","/home/sungmin/dummy_programs/dummy.txt",NULL};
execv("/home/sungmin/dummy_programs/pro2",argv);
    exit(127); 
}
else { 
    printf("Iam parent, waiting for child process to exit\n\n");        
    waitpid(child,0,0); 
    printf("Existing parent\n\n");
}

/* Don't forget to free the mmapped memory*/
if (munmap(pmap, fileInfo.st_size) == -1)
{
    close(fd);
    perror("Error un-mmapping the file");
    exit(EXIT_FAILURE);
}

/* Un-mmaping doesn't close the file, so we still need to do that.*/
close(fd);

代码程序2(打开与program1相同的文件并写入program1传递的文本)

 size_t i;
int fd;
char *pmap;
pid_t child;
struct stat fileInfo = {0};
const char *text = argv[0];

fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);

if (fd == -1)
{
    perror("Error opening file for writing");
    exit(EXIT_FAILURE);
}  

size_t textsize = strlen(text) + 1; // + \0 null character

if (lseek(fd, textsize-1, SEEK_SET) == -1)
{
    close(fd);
    perror("Error calling lseek() to 'stretch' the file");
    exit(EXIT_FAILURE);
}

if (write(fd, "", 1) == -1)
{
    close(fd);
    perror("Error writing last byte of the file");
    exit(EXIT_FAILURE);
}

pmap = mmap(0, textsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

if (pmap == MAP_FAILED)
{
    close(fd);
    perror("Error mmapping the file");
    exit(EXIT_FAILURE);
}

/* Writting users text to file */
for (i = 0; i < textsize; i++)
{
    pmap[i] = text[i];  
}   

// Write it now to disk
if (msync(pmap, textsize, MS_SYNC) == -1)
{
    perror("Could not sync the file to disk");
}

/* Don't forget to free the mmapped memory*/
if (munmap(pmap, textsize) == -1)
{
    close(fd);
    perror("Error un-mmapping the file");
    exit(EXIT_FAILURE);
}

/* Un-mmaping doesn't close the file, so we still need to do that.*/
close(fd);  

1 个答案:

答案 0 :(得分:2)

在映射之前,您需要使用truncate来扩展文件长度。

是的,函数名称听起来不对,但truncate实际上可以将文件长度设置为任意数字。请务必使用4K的倍数以获得最佳效果。

然后,如果您希望保持映射打开以查看程序1和2之间的数据,则需要删除ANONYMOUS并在程序1中使用MAP_SHARED进行映射。不共享的映射不会显示更改由其他程序制作。或者它可能,如果它必须从磁盘重新加载。这很奇怪,不要混合共享和非共享映射。

一旦您更改了程序1以使用truncate,请将lseekwrite代码从程序2中删除。该文件已经由程序创建和扩展1。