Файли, зіставлені з пам'яттю, можна використовувати або для заміни доступу для читання / запису, або для підтримки одночасного спільного використання. Коли ви використовуєте їх для одного механізму, ви отримуєте і інший.
Замість того, щоб шукати, писати та читати у файлі, ви відображаєте його у пам’яті та просто отримуєте доступ до бітів там, де ви їх очікуєте.
Це може бути дуже зручно, і в залежності від інтерфейсу віртуальної пам'яті може підвищити продуктивність. Покращення продуктивності може відбутися, оскільки операційна система тепер може керувати цим колишнім "файловим введенням-виведенням" разом із усіма іншими програмами, що мають доступ до пам'яті, і може (теоретично) використовувати алгоритми підкачки та ін., Що вона вже використовує для підтримки віртуальна пам’ять для решти вашої програми. Однак це залежить від якості вашої основної системи віртуальної пам'яті. Анекдоти, про які я чув, говорять, що системи віртуальної пам'яті Solaris та * BSD можуть покращити продуктивність, ніж система віртуальних машин Linux, але я не маю емпіричних даних, щоб підтвердити це. YMMV.
Паралельність з’являється в картині, коли ви розглядаєте можливість декількох процесів із використанням одного і того ж «файлу» через зіставлену пам’ять. У моделі читання / запису, якщо два процеси писали в одну і ту ж область файлу, ви могли б бути майже впевнені, що одна з даних процесу надійде у файл, замінивши дані іншого процесу. Ви отримаєте то одне, чи інше - але не якесь дивне змішування. Я повинен визнати, що я не впевнений, чи це поведінка, передбачена будь-яким стандартом, але це те, на що ви могли б покластися. (Це насправді agood подальше запитання!)
Натомість у зображеному світі уявіть собі два процеси, які «пишуть». Вони роблять це, роблячи «сховища пам’яті», що призводить до того, що O / S передає дані на диск - врешті-решт. Але тим часом можна очікувати накладання записів, що перекриваються.
Ось приклад. Скажімо, у мене є два процеси, обидва записують 8 байт зі зміщенням 1024. Процес 1 пише "11111111", а процес 2 пише "22222222". Якщо вони використовують файловий ввід / вивід, то ви можете собі уявити, глибоко в O / S, є буфер, заповнений 1s, і буфер, заповнений 2s, обидва направляються до одного місця на диску. Один з них збирається туди потрапити першим, а другий другим. У цьому випадку виграє другий. Однак , якщо я використовую підхід до файлів, що відображається у пам'яті, процес 1 збирається перейти до сховища пам'яті на 4 байти, за яким слідує інший накопичувач на 4 байти (припустимо, це не максимальний обсяг пам'яті). Процес 2 буде робити те саме. Виходячи з того, коли процеси запускаються, ви можете очікувати побачити будь-що з наведеного нижче:
11111111
22222222
11112222
22221111
Рішенням цього є використання явного взаємного виключення - що, мабуть, є гарною ідеєю в будь-якому випадку. Ти все одно покладався на O / S, щоб зробити "правильно" у випадку введення / виводу файлу читання / запису.
Класифікуючим примітивом взаємовиключення є мьютекс. Що стосується відображених у пам'яті файлів, я б запропонував вам поглянути на відображений на пам'ять мутекс, доступний за допомогою (наприклад) pthread_mutex_init ().
Редагувати за допомогою однієї затримки: Коли ви використовуєте зіставлені файли, виникає спокуса вбудувати покажчики до даних у файлі, у самому файлі (подумайте, пов’язаний список зберігається у зіставленому файлі). Ви не хочете цього робити, оскільки файл може бути зіставлений з різними абсолютними адресами в різний час або в різних процесах. Замість цього використовуйте зсуви в межах зіставленого файлу.