Краткий ответ - использовать madvise(addr, len, MADV_DONTFORK)
в любых буферах пользовательского пространства, которые вы предоставляете своему драйверу.Это говорит ядру, что сопоставление не следует копировать из родительского в дочернее, и поэтому CoW отсутствует.
Недостатком является то, что дочерний объект не наследует сопоставление по этому адресу, поэтому, если вы хотите, чтобы дочерний процесс затем запускалсяс помощью драйвера потребуется переназначить эту память.Но это довольно легко сделать в пользовательском пространстве.
Обновление : буфер в стеке проблематичен, я не уверен, что вы вообще можете сделать его безопасным.
Вы не можете пометить его DONTFORK
, потому что ваш ребенок может работать на этой странице стека, когда он разветвляется, или (что еще хуже) может выполнить функцию, возвращающуюся позже, и попадет на страницу неотображенного стека.(Я даже проверял это, вы можете с радостью пометить свой стек DONTFORK, когда вы разветвляетесь, происходят плохие вещи.)
Другой способ избежать CoW - создать общее отображение, но вы не можете отобразить свой стекподелился по очевидным причинам.
Это означает, что вы рискуете CoW, если вы форк.Даже если дочерний процесс «просто» исполняет, он все равно может коснуться страницы стека и вызвать CoW, что приведет к тому, что родитель получит другую страницу, что плохо.
Единственный минус в вашу пользу - это код, использующийбуфер в стеке должен беспокоиться только о коде, который он вызывает, т.е.вы не можете использовать встроенный буфер после того, как функция вернулась.Так что вам нужно только проверять своих вызываемых, и если они никогда не раскошеливаются, вы в безопасности, но это все еще может быть неосуществимо и хрупко, если код когда-либо изменится.
Я думаю, что вы действительно хотите иметь всю памятьэто дается вашему драйверу из пользовательского распределителя в пользовательском пространстве.Это не должно быть так навязчиво.Распределитель может либо mmap
напрямую подключаться к вашему устройству, как предлагалось в другом ответе, либо просто использовать анонимные mmap
, madvise(DONTFORK)
и, вероятно, mlock()
, чтобы избежать замены.