Вопрос

Я написал код для записи содержимого в сопоставленный буфер, который сопоставляется с помощью системного вызова 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");
}
}
Это было полезно?

Решение

Если вы хотите, чтобы ваши изменения отражались в файле на диске, вы должны сопоставить файл как MAP_SHARED, а не как MAP_PRIVATE.

Кроме того, вы не можете расширить файл, просто написав за пределами конца сопоставления.Вы должны использовать ftruncate() для расширения файла до нового размера, а затем изменить отображение, чтобы включить новую часть файла.Переносимый способ изменить отображение - отменить отображение, а затем воссоздать его с новым размером;в Linux вместо этого можно использовать mremap().

Ваши переменные len и len_file должны иметь тип size_t, и вы должны использовать memcpy(), а не strcat(), поскольку вы точно знаете длину строки, где именно хотите ее скопировать, а вы не хотите скопировать нулевой символ конца.

Следующая модификация вашего кода работает в Linux (с использованием mremap()):

родовое слово

Другие советы

Обратите внимание, что вы предоставили сопоставление для файла, которое в точности соответствует размеру файла.Если вы создадите файл при вызове open(2), он будет иметь длину 0, и я не удивлюсь, если ядро не потрудится настроить какое-либо отображение памяти из 0 отображение длины.(Может быть, так и есть?Я никогда не пробовал...)

Я бы предложил использовать ftruncate(2) чтобы увеличить длину вашего файла до того, как выполнение сопоставления.(Обратите внимание, что расширение файлов с помощью ftruncate(2) не очень портативен;не все платформы предоставляют расширенную функциональность, и не все драйверы файловой системы поддерживают расширенную функциональность.Подробную информацию смотрите на странице руководства вашей системы.)

Вы должны использовать MAP_SHARED сопоставление изменений вашего файла, которые будут сохранены на диске.

Ваше использование perror(3) это не совсем корректно; perror(3) будет нет завершите работу вашей программы, чтобы она продолжала выполняться с неверными допущениями:

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

Следует прочитать:

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

(Или exit(EXIT_FAILURE) если вы хотите быть более переносимым - я нахожу, что это немного сложнее для глаз, но я живу в стране Linux.)

strcat(3) ожидает найти нулевой символ ASCII (байтовое значение 0x00, Представление C '\0') - обычный маркер конца строки на языке Си - в конце dest струна.Ваш файл не будет содержать NUL в формате ASCII, если вы создадите его в этой программе - в конце концов, его длина равна нулю - и я не знаю последствий попытки прочитать файл с нулевым байтом через mmap(2).Если файл уже существует и в нем есть данные, он вероятно в файле нет кодировки ASCII NUL. strcat(3) это почти наверняка неправильный инструмент для записи в ваш файл.(В любом случае, никому не нужны нули в формате ASCII в своих файлах.) Попробуйте memcpy(3) вместо этого.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top