Linux shm что это

Обновлено: 07.07.2024

/ Dev / shm / - очень полезный каталог в linux, потому что этот каталог находится не на жестком диске, а в памяти. Поэтому в Linux нет необходимости тратить много усилий на создание виртуального диска, непосредственное использование / dev / shm / может обеспечить очень хороший эффект оптимизации. / dev / shm / Следует обратить внимание на проблему с пропускной способностью: в Linux по умолчанию она составляет не более половины размера памяти, что можно увидеть с помощью команды df -h. Но он на самом деле не занимает эту память. Если в каталоге / dev / shm / нет файла, то занимаемая им память фактически равна 0 байтам, если это максимум 1 ГБ и в нем 100 МБ файлов, остальные 900 МБ. Он по-прежнему может использоваться другими приложениями, но занимаемая им память 100 МБ никогда не будет перераспределена системой. В противном случае, кто осмелится сохранить файлы?

По умолчанию система будет загружать / dev / shm, которая является так называемой tmpfs (система виртуальной памяти). Некоторые люди говорят, что она отличается от ramdisk (виртуальный диск). Как и виртуальный диск, tmpfs может использовать вашу оперативную память, но он также может использовать ваш раздел подкачки для хранения. А традиционный виртуальный диск - это блочное устройство, и для его использования требуется команда типа mkfs. Tmpfs - это файловая система, а не блочное устройство, вы просто устанавливаете его, и его можно использовать. Самая большая особенность tmpfs заключается в том, что его пространство хранения находится в виртуальной памяти (VM), которая управляется подсистемой vm внутри ядра linux , Размер виртуальной машины под Linux состоит из RM (реальной памяти) и подкачки. Размер RM - это размер физической памяти, а размер подкачки определяется вами. Swap - это пространство памяти, виртуализированное жестким диском, поэтому скорость чтения и записи намного ниже, чем RM (реальная память), Когда процесс запрашивает определенный объем памяти, например, когда подсистема vm ядра обнаруживает, что RM недостаточно, он будет обмениваться некоторыми редко используемыми данными в RM в Swap. Если вам нужно повторно использовать эти данные, перенесите их из Swap Обмен на РМ.

Виртуальная машина состоит из двух частей: RM + Swap, поэтому максимальное пространство хранения tmpfs не превышает (размер RM + размер Swap). Но для самой tmpfs он не знает, является ли используемое им пространство RM или Swap, и все они управляются подсистемой vm ядра. Размер tmpfs по умолчанию равен половине RM. Если ваша физическая память равна 1024M, то размер tmpfs по умолчанию составляет 512M. В нормальных условиях он настроен на размер меньше физической памяти. Размер конфигурации tmpfs на самом деле не занимает эту память.Если в каталоге / dev / shm / нет файла, то занимаемая им память фактически равна 0 байтам, если это максимум 1 ГБ, в нем содержится 100 МБ файлов, а остальные 900M все еще может использоваться другими приложениями, но занимаемая им память 100M не будет разделяться системой. При удалении файлов в tmpfs драйвер файловой системы tmpfs динамически сокращает файловую систему и освобождает ресурсы виртуальной машины.

У tmpfs есть следующие преимущества:

1. Размер динамической файловой системы.
2. Еще одним важным преимуществом tmpfs является его молниеносная скорость. Поскольку типичная файловая система tmpfs полностью находится в оперативной памяти, чтение и запись могут быть практически мгновенными.
3. Данные tmpfs не будут сохранены после перезапуска, поскольку виртуальная память по своей природе является энергозависимой. Поэтому необходимо сделать несколько сценариев для выполнения таких операций, как загрузка и привязка.

Во-вторых, измените размер / dev / shm

Максимальная половина размера памяти по умолчанию может быть недостаточной в некоторых случаях, и число inode по умолчанию, как правило, невелико. Как правило, вам нужно увеличить его. Вы можете использовать команду mount для управления им.

На машине 2G максимальная емкость устанавливается на 1,5 ГБ, а число инодов - на 1000000, что означает, что можно хранить до миллиона небольших файлов.

Если вам нужно постоянно изменять значение / dev / shm, вам нужно изменить / etc / fstab

Примечание. Используйте команду df -h для просмотра результатов.

Три, / dev / shm приложение

Сначала создайте папку tmp в / dev / shm, а затем свяжите ее с фактическим / tmp

После использования команды mount --bind olddir newerdir для монтирования каталога в другой каталог вся информация, такая как разрешения и владелец newerdir, изменится. Подключенный каталог наследует все атрибуты подключенного каталога, кроме имени. В режиме управления памятью amm в Oracle 11g используется / dev / shm, поэтому иногда изменение MEMORY_TARGET или MEMORY_MAX_TARGET приводит к ошибке ORA-00845.


Разделяемая память — самый быстрый способ обмена данными между процессами. Но в отличие от потоковых механизмов (трубы, сокеты всех мастей, файловые очереди . ), здесь у программиста полная свобода действий, в результате пишут кто во что горазд.

Так и автор однажды задался мыслью, а что если … если произойдёт вырождение адресов сегментов разделяемой памяти в разных процессах. Вообще-то именно это происходит, когда процесс с разделяемой памятью делает fork, а как насчет разных процессов? Кроме того, не во всех системах есть fork.

Казалось бы, совпали адреса и что с того? Как минимум, можно пользоваться абсолютными указателями и это избавляет от кучи головной боли. Станет возможно работать со строками и контейнерами С++, сконструированными из разделяемой памяти.

Отличный, кстати, пример. Не то, чтобы автор сильно любил STL, но это возможность продемонстрировать компактный и всем понятный тест на работоспособность предлагаемой методики. Методики, позволяющей (как видится) существенно упростить и ускорить межпроцессное взаимодействие. Вот работает ли она и чем придётся заплатить, будем разбираться далее.

Введение

Идея разделяемой памяти проста и изящна — поскольку каждый процесс действует в своём виртуальном адресном пространстве, которое проецируется на общесистемное физическое, так почему бы не разрешить двум сегментам из разных процессов смотреть на одну физическую область памяти.

А с распространением 64-разрядных операционных систем и повсеместным использованием когерентного кэша, идея разделяемой памяти получила второе дыхание. Теперь это не просто циклический буфер — реализация “трубы” своими руками, а настоящий “трансфункционер континуума” — крайне загадочный и мощный прибор, причем, лишь его загадочность равна его мощи.

Рассмотрим несколько примеров использования.

    Протокол “shared memory” при обмене данными с MS SQL. Демонстрирует некоторое улучшение производительности (


Для проверки концепции требуется минимально-осмысленная задача:

  • есть аналог std::map<std::string, std::string>, расположенный в разделяемой памяти
  • имеем N процессов, которые асинхронно вносят/меняют значения с префиксом, соответствующим номеру процесса (ex: key_1_… для процесса номер 1)
  • в результате, конечный результат мы можем проконтролировать

Аллокатор STL

Допустим, для работы с разделяемой памятью существуют функции xalloc/xfree как аналоги malloc/free. В этом случае аллокатор выглядит так:


Этого достаточно, чтобы подсадить на него std::map & std::string


Прежде чем заниматься заявленными функциями xalloc/xfree, которые работают с аллокатором поверх разделяемой памяти, стоит разобраться с самой разделяемой памятью.

Разделяемая память

Разные потоки одного процесса находятся в одном адресном пространстве, а значит каждый не thread_local указатель в любом потоке смотрит в одно и то же место. С разделяемой памятью, чтобы добиться такого эффекта приходится прилагать дополнительные усилия.

Windows

    Создадим отображение файла в память. Разделяемая память так же как и обычная покрыта механизмом подкачки, здесь помимо всего прочего определяется, будем ли мы пользоваться общей подкачкой или выделим для этого специальный файл.


segment size 0 означает, что будет использован размер, с которым создано отображение с учетом сдвига.

Linux

Здесь принципиально всё то же самое.

    Создаём объект разделяемой памяти

Ограничения на подсказку

Что касается подсказки (hint), каковы ограничения на её значение? Вообще-то, есть разные виды ограничений.

Во-первых, архитектурные/аппаратные. Здесь следует сказать несколько слов о том, как виртуальный адрес превращается в физический. При промахе в кэше TLB, приходится обращаться в древовидную структуру под названием “таблица страниц” (page table). Например, в IA-32 это выглядит так:


Фиг.2 случай 4K страниц, взято здесь

В AMD64 картина выглядит немного по-другому.


Фиг.3 AMD64, 4K страницы, взято отсюда

В CR3 теперь 40 значимых разрядов вместо 20 ранее, в дереве 4 уровня страниц, физический адрес ограничен 52 разрядами при том, что виртуальный адрес ограничен 48 разрядами.

И лишь в(начиная с) микроархитектуре Ice Lake(Intel) дозволено использовать 57 разрядов виртуального адреса (и по-прежнему 52 физического) при работе с 5-уровневой таблицей страниц.

До сих пор мы говорили лишь об Intel/AMD. Просто для разнообразия, в архитектуре Aarch64 таблица страниц может быть 3 или 4 уровневой, разрешая использование 39 или 48 разрядов в виртуальном адресе соответственно (1).

Во вторых, программные ограничения. Microsoft, в частности, налагает (44 разряда до 8.1/Server12, 48 начиная с) таковые на разные варианты ОС исходя из, в том числе, маркетинговых соображений.

Между прочим, 48 разрядов, это 65 тысяч раз по 4Гб, пожалуй, на таких просторах всегда найдётся уголок, куда можно приткнуться со своим hint-ом.

Аллокатор разделяемой памяти

Во первых. Аллокатор должен жить на выделенной разделяемой памяти, размещая все свои внутренние данные там же.

Во вторых. Мы говорим о средстве межпроцессного общения, любые оптимизации, связанные с использованием TLS неуместны.

В третьих. Раз задействовано несколько процессов, сам аллокатор может жить очень долго, особую важность принимает уменьшение внешней фрагментации памяти.

В четвертых. Обращения к ОС за дополнительной памятью недопустимы. Так, dlmalloc, например, выделяет фрагменты относительно большого размера непосредственно через mmap. Да, его можно отучить, завысив порог, но тем не менее.

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

Итого, учитывая всё вышесказанное а так же потому, что под рукой оказался живой аллокатор методом близнецов (любезно предоставленный Александром Артюшиным, слегка переработанный), выбор оказался несложным.

Описание деталей реализации оставим до лучших времён, сейчас интересен публичный интерфейс:


Деструктор тривиальный т.к. никаких посторонних ресурсов BuddyAllocator не захватывает.

Последние приготовления

Раз всё размещено в разделяемой памяти, у этой памяти должен быть заголовок. Для нашего теста этот заголовок выглядит так:

  • own_addr_ прописывается при создании разделяемой памяти для того, чтобы все, кто присоединяются к ней по имени могли узнать фактический адрес (hint) и пере-подключиться при необходимости
  • вот так хардкодить размеры нехорошо, но для тестов приемлемо
  • вызывать конструктор(ы) должен процесс, создающий разделяемую память, выглядит это так:

Эксперимент

Сам тест очень прост:


Curid — это номер процесса/потока, процесс, создавший разделяемую память имеет нулевой curid, но для теста это неважно.
Qmap, LOCK/UNLOCK для разных тестов разные.

Проведем несколько тестов

  1. THR_MTX — многопоточное приложение, синхронизация идёт через std::recursive_mutex,
    qmap — глобальная std::map<std::string, std::string>
  2. THR_SPN — многопоточное приложение, синхронизация идёт через спинлок:

1 2 4 8 16
THR_MTX 1’56’’ 5’41’’ 7’53’’ 51’38’’ 185’49
THR_SPN 1’26’’ 7’38’’ 25’30’’ 103’29’’ 347’04’’
PRC_SPN 1’24’’ 7’27’’ 24’02’’ 92’34’’ 322’41’’
PRC_MTX 4’55’’ 13’01’’ 78’14’’ 133’25’’ 357’21’’

Эксперимент проводился на двухпроцессорном (48 ядер) компьютере с Xeon® Gold 5118 2.3GHz, Windows Server 2016.

Итого

  • Да, использовать объекты/контейнеры STL (размещенные в разделяемой памяти) из разных процессов можно при условии, что они сконструированы надлежащим образом.
  • По производительности явного проигрыша нет, скорее наоборот, PRC_SPN даже чуть быстрее THR_SPN. Поскольку разница здесь только в аллокаторе, значит BuddyAllocator чуть быстрее malloc\free от MS (при невысокой конкуренции).
  • Проблемой является высокая конкуренция. Даже самый быстрый вариант — многопоточность + std::mutex в этих условиях работает безобразно медленно. Здесь были бы полезны lock-free контейнеры, но это уже тема для отдельного разговора.

Вдогонку

Разделяемую память часто используют для передачи больших потоков данных в качестве своеобразной “трубы”, сделанной своими руками. Это отличная идея даже несмотря на необходимость устраивать дорогостоящую синхронизацию между процессами. То, что она не дешевая, мы видели на тесте PRC_MTX, когда работа даже без конкуренции, внутри одного процесса ухудшила производительность в разы.

Объяснение дороговизны простое, если std::(recursive_)mutex (критическая секция под windows) умеет работать как спинлок, то именованный мутекс — это системный вызов, вход в режим ядра с соответствующими издержками. Кроме того, потеря потоком/процессом контекста исполнения это всегда очень дорого.

Но раз синхронизация процессов неизбежна, как же нам уменьшить издержки? Ответ давно придуман — буферизация. Синхронизируется не каждый отдельный пакет, а некоторый объем данных — буфер, в который эти данные сериализуются. Если буфер заметно больше размера пакета, то и синхронизироваться приходится заметно реже.

Удобно смешивать две техники — данные в разделяемой памяти, а через межпроцессный канал данных (ex: петля через localhost) отправляют только относительные указатели (от начала разделяемой памяти). Т.к. указатель обычно меньше пакета данных, удаётся сэкономить на синхронизации.

А в случае, когда разным процессам доступна разделяемая память по одному виртуальному адресу, можно еще немного добавить производительности.

  • не сериализуем данные для отправки, не десериализуем при получении
  • отправляем через поток честные указатели на объекты, созданные в разделяемой памяти
  • при получении готового (указателя) объекта, пользуемся им, затем удаляем через обычный delete, вся память автоматически освобождается. Это избавляет нас от возни с кольцевым буфером
  • можно даже посылать не указатель, а (минимально возможное — байт со значением “you have mail”) уведомление о факте наличия чего-нибудь в очереди

Напоследок

Чего нельзя делать с объектами, сконструированными в разделяемой памяти.

  1. Использовать RTTI. По понятным причинам. Std::type_info объекта существует вне разделяемой памяти и недоступен в разных процессах.
  2. Использовать виртуальные методы. По той же причине. Таблицы виртуальных функций и сами функции недоступны в разных процессах.
  3. Если говорить об STL, все исполняемые файлы процессов, разделяющих память, должны быть скомпилированы одним компилятором с одними настройками да и сама STL должна быть одинаковой.

UPD: исходники BuddyAllocator выложены здесь под BSD лицензией.

Отступление: данная статья является учебной и расчитана на людей, только еще вступающих на путь системного программирования. Ее главный замысел — познакомиться с различными способами взаимодействия между процессами на POSIX-совместимой ОС.

Именованный канал

Примечание: mode используется в сочетании с текущим значением umask следующим образом: (mode &

umask). Результатом этой операции и будет новое значение umask для создаваемого нами файла. По этой причине мы используем 0777 (S_IRWXO | S_IRWXG | S_IRWXU), чтобы не затирать ни один бит текущей маски.

Как только файл создан, любой процесс может открыть этот файл для чтения или записи также, как открывает обычный файл. Однако, для корректного использования файла, необходимо открыть его одновременно двумя процессами/потоками, одним для получение данных (чтение файла), другим на передачу (запись в файл).

В случае успешного создания FIFO файла, mkfifo() возвращает 0 (нуль). В случае каких либо ошибок, функция возвращает -1 и выставляет код ошибки в переменную errno.

  • EACCES — нет прав на запуск (execute) в одной из директорий в пути pathname
  • EEXIST — файл pathname уже существует, даже если файл — символическая ссылка
  • ENOENT — не существует какой-либо директории, упомянутой в pathname, либо является битой ссылкой
  • ENOSPC — нет места для создания нового файла
  • ENOTDIR — одна из директорий, упомянутых в pathname, на самом деле не является таковой
  • EROFS — попытка создать FIFO файл на файловой системе «только-на-чтение»

Пример

mkfifo.c

Мы открываем файл только для чтения (O_RDONLY). И могли бы использовать O_NONBLOCK модификатор, предназначенный специально для FIFO файлов, чтобы не ждать когда с другой стороны файл откроют для записи. Но в приведенном коде такой способ неудобен.

Компилируем программу, затем запускаем ее:

В соседнем терминальном окне выполняем:

В результате мы увидим следующий вывод от программы:

Разделяемая память


Следующий тип межпроцессного взаимодействия — разделяемая память (shared memory). Схематично изобразим ее как некую именованную область в памяти, к которой обращаются одновременно два процесса:

Для выделения разделяемой памяти будем использовать POSIX функцию shm_open():

Функция возвращает файловый дескриптор, который связан с объектом памяти. Этот дескриптор в дальнейшем можно использовать другими функциями (к примеру, mmap() или mprotect()).

Целостность объекта памяти сохраняется, включая все данные связанные с ним, до тех пор пока объект не отсоединен/удален (shm_unlink()). Это означает, что любой процесс может получить доступ к нашему объекту памяти (если он знает его имя) до тех пор, пока явно в одном из процессов мы не вызовем shm_unlink().

  • O_RDONLY — открыть только с правами на чтение
  • O_RDWR — открыть с правами на чтение и запись
  • O_CREAT — если объект уже существует, то от флага никакого эффекта. Иначе, объект создается и для него выставляются права доступа в соответствии с mode.
  • O_EXCL — установка этого флага в сочетании с O_CREATE приведет к возврату функцией shm_open ошибки, если сегмент общей памяти уже существует.

После создания общего объекта памяти, мы задаем размер разделяемой памяти вызовом ftruncate(). На входе у функции файловый дескриптор нашего объекта и необходимый нам размер.

Пример

Следующий код демонстрирует создание, изменение и удаление разделяемой памяти. Так же показывается как после создания разделяемой памяти, программа выходит, но при следующем же запуске мы можем получить к ней доступ, пока не выполнен shm_unlink().

shm_open.c

После создания объекта памяти мы установили нужный нам размер shared memory вызовом ftruncate(). Затем мы получили доступ к разделяемой памяти при помощи mmap(). (Вообще говоря, даже с помощью самого вызова mmap() можно создать разделяемую память. Но отличие вызова shm_open() в том, что память будет оставаться выделенной до момента удаления или перезагрузки компьютера.)

Компилировать код на этот раз нужно с опцией -lrt:

Смотрим что получилось:

Аргумент «create» в нашей программе мы используем как для создания разделенной памяти, так и для изменения ее содержимого.

Зная имя объекта памяти, мы можем менять содержимое разделяемой памяти. Но стоит нам вызвать shm_unlink(), как память перестает быть нам доступна и shm_open() без параметра O_CREATE возвращает ошибку «No such file or directory».

Семафор

Семафор — самый часто употребляемый метод для синхронизации потоков и для контролирования одновременного доступа множеством потоков/процессов к общей памяти (к примеру, глобальной переменной). Взаимодействие между процессами в случае с семафорами заключается в том, что процессы работают с одним и тем же набором данных и корректируют свое поведение в зависимости от этих данных.

  1. семафор со счетчиком (counting semaphore), определяющий лимит ресурсов для процессов, получающих доступ к ним
  2. бинарный семафор (binary semaphore), имеющий два состояния «0» или «1» (чаще: «занят» или «не занят»)

Семафор со счетчиком

Смысл семафора со счетчиком в том, чтобы дать доступ к какому-то ресурсу только определенному количеству процессов. Остальные будут ждать в очереди, когда ресурс освободится.

Итак, для реализации семафоров будем использовать POSIX функцию sem_open():

В функцию для создания семафора мы передаем имя семафора, построенное по определенным правилам и управляющие флаги. Таким образом у нас получится именованный семафор.
Имя семафора строится следующим образом: в начале идет символ "/" (косая черта), а следом латинские символы. Символ «косая черта» при этом больше не должен применяться. Длина имени семафора может быть вплоть до 251 знака.

Если нам необходимо создать семафор, то передается управляющий флаг O_CREATE. Чтобы начать использовать уже существующий семафор, то oflag равняется нулю. Если вместе с флагом O_CREATE передать флаг O_EXCL, то функция sem_open() вернет ошибку, в случае если семафор с указанным именем уже существует.

Параметр mode задает права доступа таким же образом, как это объяснено в предыдущих главах. А переменной value инициализируется начальное значение семафора. Оба параметра mode и value игнорируются в случае, когда семафор с указанным именем уже существует, а sem_open() вызван вместе с флагом O_CREATE.

Для быстрого открытия существующего семафора используем конструкцию:
, где указываются только имя семафора и управляющий флаг.

Пример семафора со счетчиком

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

sem_open.c

В одной консоли запускаем:

В соседней консоли запускаем:

Бинарный семафор

Вместо бинарного семафора, для которого так же используется функция sem_open, я рассмотрю гораздо чаще употребляемый семафор, называемый «мьютекс» (mutex).

Мьютекс по существу является тем же самым, чем является бинарный семафор (т.е. семафор с двумя состояниями: «занят» и «не занят»). Но термин «mutex» чаще используется чтобы описать схему, которая предохраняет два процесса от одновременного использования общих данных/переменных. В то время как термин «бинарный семафор» чаще употребляется для описания конструкции, которая ограничивает доступ к одному ресурсу. То есть бинарный семафор используют там, где один процесс «занимает» семафор, а другой его «освобождает». В то время как мьютекс освобождается тем же процессом/потоком, который занял его.

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

Для использования мьютекса необходимо вызвать функцию pthread_mutex_init():

Функция инициализирует мьютекс (перемнную mutex) аттрибутом mutexattr. Если mutexattr равен NULL, то мьютекс инициализируется значением по умолчанию. В случае успешного выполнения функции (код возрата 0), мьютекс считается инициализированным и «свободным».

  • EAGAIN — недостаточно необходимых ресурсов (кроме памяти) для инициализации мьютекса
  • ENOMEM — недостаточно памяти
  • EPERM — нет прав для выполнения операции
  • EBUSY — попытка инициализировать мьютекс, который уже был инициализирован, но не унечтожен
  • EINVAL — значение mutexattr не валидно

Функция pthread_mutex_lock(), если mutex еще не занят, то занимает его, становится его обладателем и сразу же выходит. Если мьютекс занят, то блокирует дальнейшее выполнение процесса и ждет освобождения мьютекса.
Функция pthread_mutex_trylock() идентична по поведению функции pthread_mutex_lock(), с одним исключением — она не блокирует процесс, если mutex занят, а возвращает EBUSY код.
Фунция pthread_mutex_unlock() освобождает занятый мьютекс.

  • EINVAL — mutex неправильно инициализирован
  • EDEADLK — мьютекс уже занят текущим процессом
  • EBUSY — мьютекс уже занят
  • EINVAL — мьютекс неправильно инициализирован
  • EINVAL — мьютекс неправильно инициализирован
  • EPERM — вызывающий процесс не является обладателем мьютекса

Пример mutex

mutex.c

Данный пример демонстрирует совместный доступ двух потоков к общей переменной. Один поток (первый поток) в автоматическом режиме постоянно увеличивает переменную counter на единицу, при этом занимая эту переменную на целую секунду. Этот первый поток дает второму доступ к переменной count только на 10 миллисекунд, затем снова занимает ее на секунду. Во втором потоке предлагается ввести новое значение для переменной с терминала.

Если бы мы не использовали технологию «мьютекс», то какое значение было бы в глобальной переменной, при одновременном доступе двух потоков, нам не известно. Так же во время запуска становится очевидна разница между pthread_mutex_lock() и pthread_mutex_trylock().

Компилировать код нужно с дополнительным параметром -lpthread:

Запускаем и меняем значение переменной просто вводя новое значение в терминальном окне:

Вместо заключения

В следующих статьях я хочу рассмотреть технологии d-bus и RPC. Если есть интерес, дайте знать.
Спасибо.

UPD: Обновил 3-ю главу про семафоры. Добавил подглаву про мьютекс.


Динамические изменения на странице (Это вообще к асп.нет имеет отношение?)
На странице имеются поля созданные таким вот образом &lt;input type=&quot;text&quot; name=&quot;Text&quot; /&gt;&lt;input.

Django: Что это такое вообще? Что я пропустил в изучении Python?
Какой язык используется в фигурных скобках? Это разве python? Если кто знает то дайте мне ссылку.


Как работает оператор **, что это вообще такое?
Где то на майлах нашел возведение в корень при помощи **.5 так..что это вообще за херь и что она.

apache веб сервер что это такое вообще?
почитал что apache это веб сервер, однако читал но всё равно не понятно что делает этот самый.

xlxndr, /dev/shm - это tmpfs, она всегда занимает 50% ОЗУ, но "занимает" не в привычном смысле слова, т. е. там ничего не хранится. Там можно без лишних телодвижений хранить файлы, для которых временно (до перезагрузки!) нужна очень быстрая память (например, если видео редактировать будете).

Вы имеете в виду ОЗУ? Они используют её всю.

А если я создам некоторый раздел /dev/shm/temp и примонтирую его к /temp, определив размер 20% RAM, то будет ли недоступна эта память как оперативная память для работы программ?

Т.е., ОЗУ используется совместно приложениями и хранилищем файлов /dev/shm/tmp, так? При этом определение размера для /dev/shm/temp в таблице монтирования /etc/fstab не отрезает кусок памяти от ОЗУ и не запрещает использовать его же программам?

/dev/shm может быть увеличина, например до 80% озу в таблице /etc/fstab. Я привильно понимаю, что это никак не отразится на работе программ, если папка /dev/shm/tmp будет пуста, и это отрежет ровно 80% от ОЗУ, доступной программам, если папка /dev/shm/tmp будет занята на 100%? Не понятен принцип, который отрезает 50%, т.к. должен не в % отрезать, а просто отрезать кусок количестве Гб, минимально необходимый для системы, а остальное - разрешать к монтированию в /dev/shm.

Тогда, если такая ситуация: предполагается использовать сервер баз данных, и имеется 32Гб ОЗУ, а отведенная под /dev/shm/tmp папка будет занята именно на 99%, там будут храниться temp tablespace и поисковые индексы, то сколько в таком случае рационально отдавать на такую папу % от ОЗУ. Явно ведь не 50%, т.к. системе будет жирновато 16Гб, если сервак больше не используется ни для каких целей. Я так понимаю, оставлять системе около 1-2Гб, т.е. в % это 4-5% ОЗУ?

Читайте также: