Memory grants is a inter-procedure communication mechanism to allow processes to transfer large amounts of data. An alternative name of this IPC mechanism is safecopies, as the low-kernel kernel system calls related to using memory grants all contain “safe” in their name.
User-mode processes cannot escape their virtual address space, i.e. they cannot read or write the memory of other processes ; they have to use kernel-provided IPC functionality to exchange data with them. Traditional POSIX solutions to this problem are pipe, sockets, shared memory, signals and others.
The Minix micro-kernel provides fixed-size 64 bytes message passing, but transferring large amounts of data with those messages would be very inefficient. One POSIX IPC could have been implemented in the micro-kernel, however the needs and goals of Minix makes them unsuited for the task, as such an IPC has to satisfy all following criteria at the same time :
Memory grants were created to address the need of IPC provided by the micro-kernel for large amounts of data. This mechanism allows processes to grant access to a well defined region of their memory to another process.
There are three types of memory grants. All share common attributes :
By convention, the granter is the process that created and owns the grant ; the grantee is the process to which the memory grant was granted.
Granters maintain their array of grants in their memory space, the micro-kernel is informed of this array by the SYS_SETGRANT kernel system call. Grantees can, depending on which operations are allowed, read and/or write (copy or set bytes) to the specified memory region of the granter through the relevant kernel system calls.
Those kernel calls are wrapped by higher-level functions in the libsys library (the cpf_* family of functions). Protocol abstraction libraries can provide higher-level semantics to memory grants : an example is directory listing inside a file server, where fsdriver collects directories entries through a callback function and sends them to VFS through a memory grant.
Memory grants are identified by a memory grant credential (an integer of type cp_grant_id_t). Those credentials are transmitted to grantees by message passing.
There are three types of memory grants, depending on whether the grant was transferred from a process to another or not.
Direct grants are the simplest type of grants. They specify that a memory region of the granter is accessible by the grantee. They are direct in the sense that they haven't been transferred : the granter is the owner of the memory region, there is no middleman between the two.
Indirect grants are grants that have been transferred by a grantee : the grantee delegates its grant to another process. The grantee becomes a granter and then pass a newly created memory grant credential to the new grantee. The memory grant thus forms a linked list of indirect grants, with a direct grant at the start.
Indirect grant can themselves be transferred to another grantee by creating a new indirect grant.
Magic grants are grants that are made by one process for memory in another process. Right now, the only service that may create magic grants, is VFS. VFS uses magic grants to give other services, like file systems and drivers, direct access to memory in user application processes, for example for read/write operations. Since user application processes themselves can not create grants (this requires service privileges), and all driver/filesystem I/O is mediated by VFS, magic grants serve to avoid that VFS needs to copy in and out all data transferred between applications and filesystems/drivers.