2015-12-13 5 views
1

Я пытаюсь сделать класс файла журнала, процесс, который я хочу, чтобы выполнить следующие действия:Не очень понятно, почему mmap не делает то, что я думаю, что он должен. C++ Linux

  • Открыть файл (или создать)
  • Карты файла в памяти
  • Закрыть де файл
  • Запись в память

файл будет иметь размер 1024Кб (постоянной SIZE_KB).

До сих пор это то, что я делаю:

Im создание файла с правами на чтение и запись для владельца (S_IRUSR | S_IWUSR) и разрешения на чтение для отдыха (S_IRGRP | S_IROTH).

// Open the file. If the file doesnt exists it will create it 
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; 
int fd = open(path.c_str(), O_CREAT | O_RDWR, mode); 

После этого я проверяю, если fd является -1:

if (fd < 0) 
    throw std::system_error(errno, std::system_category(), "couldnt open history"); 

#ifdef _DEBUG_ 
    std::clog << "History with file descriptor " << fd << " opened" << std::endl; 
#endif 

Теперь я карту файл, но сначала мне нужно установить переменную длину с размером файла, который должен быть Mutiple из sysconf(_SC_PAGE_SIZE):

size_t length = (int)ceil(SIZE_KB*1024.0/sysconf(_SC_PAGE_SIZE))*sysconf(_SC_PAGE_SIZE); 
/* ceil(size/page_size)*page_size*/ 

#ifdef _DEBUG_ 
    std::clog << "Length is " << length << " bytes" << std::endl; 
#endif 

Mapping, block_start частный указатель символ:

block_start = (char*)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
  • Дополнительный вопрос: M_SHARED варианта сделать эту часть памяти, доступной для других процессов (?). Почему он также используется для того, чтобы СО сохранить изменения, внесенные в виртуальную память, в фактический файл?.

Проверка на наличие ошибок:

#ifdef _DEBUG_ 
    std::clog << Returned: " << (int*)block_start << std::endl; 
#endif 

if (block_start == MAP_FAILED) 
    throw std::system_error(errno, std::system_category(), "couldnt map memory"); 

#ifdef _DEBUG_ 
    std::clog << "History memory mapped" << std::endl; 
#endif 

И закрыть файл:

int result = close(fd); 
if (result < 0) 
    throw std::system_error(errno, std::system_category(), "error closing history"); 

#ifdef _DEBUG_ 
    std::clog << "History with file descriptor " << fd << " closed" << std::endl; 
#endif 

Теперь, я должен быть в состоянии добавить информацию в отображенной памяти, так что я пытался делать:

std::cout << "Attemping to write on first" << std::endl; 
*block_start = 'A'; 
std::cout << "End" << std::endl; 

(Внутри конструктора)

Это выход у меня есть:

History with file descriptor 3 opened 
Length is 1048576 bytes 
Returned: 0x7f7e9160a000 
History memory mapped 
History with file descriptor 3 closed 
Attemping to write on first 
Bus error (core dumped) 

Я думаю, что это, возможно, придется делать с размером файла, так как созданный файл имеет 0 размер, но Im говоря ММАП сопоставить размер SIZE_KB*1024 байт, так почему это не работает?

-rw-r--r-- 1 dark dark 0 Dec 13 16:15 /home/dark/talk.log 

ответ

1

Поскольку mmap не будет отображаться за пределами размера файла. Если вы mmaping пустой файл, ваш эффективный размер mmap равен 0.

Необходимо установить размер файла с помощью truncate() или ftruncate() перед тем, как намотать его и размер файла, и размер mmapped, должен согласиться.

+0

Последнее предложение немного неправильно. Вы можете «mmap» сегмент * меньше * чем размер файла. –

+0

Спасибо, что решил проблему, я думал, что это не нужно. Любой ответ на вопрос M_SHARED? – Ediolot

+0

Потому что это то же самое. Потому что единственный способ для других процессов совместно использовать один и тот же сегмент памяти - это для mmap того же файла. Следовательно, вы должны иметь флаг MAP_SHARED, также обновляющий содержимое базового файла. В противном случае другие процессы не будут видеть изменения в файл mmapped, созданный вашим процессом. –

Смежные вопросы