Interprocess Communication Implementation
Pipe
Byte Stream
Two Processes
Unidirectional
FIFO Buffer (Anonymous/Named)
Message Queue
Message
Multiple Processes
Uni/Bidirectional
Message Queue
Semaphore
Counter
Multiple Processes
Uni/Bidirectional
Shared Counter
Shared Memory
Memory Region
Multiple Processes
Uni/Bidirectional
Memory Allocation
Signal
Signal Code
Multiple Processes
Unidirectional
Signal Queue & Process Group
Socket
Datagram
Two Processes
Uni/Bidirectional
Network Stack (IP+Port/File Path)
Pipe
Use
pipe(pipefds)
to generate two pipe descriptors (only one underlying file).The pipe in unidirectional, the read end is
pipefds[0]
and the write end ispipefds[1]
for all processes which can see the pipe.One process closes one end and performs action on the other end.
It's OK but NOT RECOMMENDED to do none of the
close
s above.
Possible Cases:
If no one is at the write end, the readers simply stop reading.
If someone is at the write end but the buffer is empty, the readers block until the buffer is not empty.
Implementation
The (simplified) in-memory description of pipe is:
The bufs
array in pipe_inode_info
consists of multiple instances of the struct pipe_buffer
. Each instance of this structure includes a struct page
and its corresponding operations.
When accessing a buf
, the underlying data is identified by pipe_buffer.offset
(the starting point) and pipe_buffer.len
(the length). For instance, in order to read from the pipe, the kernel copies [pipe_buffer.offset, pipe_buffer.offset + pipe_buffer.len]
to user space.
Generally, the "byte stream" of a pipe consists of an array of pipe_buffer
s, which is essentially an array of pages.
The pipe created using the pipe
function is known as an anonymous pipe and is identified by file descriptors. Anonymous pipes can be shared between processes through forking. However, if we want to establish a pipe between two distant processes, we need to use the mkfifo
function to create named pipes.
Shared Memory
In Linux kernel, the abstraction for shared memory is shmid_kernel
:
shm_perm
: the standard IPC permission set. This structure is used to control access to the shared memory segment.file
: the file that backs the shared memory segment. Ultimately,file
points to a set of memory pages, which is the actual shared memory segment.shm_nattach
: the number of current attaches to the shared memory segment.shm_segsz
: size of the shared memory segment in bytes.time64_t shm_atim, shm_dtim, shm_ctim
:shm_atim
is the last attach time,shm_dtim
is the last detach time, andshm_ctim
is the last change time.shm_cprid, shm_lprid
: representing the creator PID (process ID) and last operator PID.shm_clist
: This is a list head used to link all shared memory segments created by a single task. It's part of a linked list data structure.ns
: the shared memory segment is visible only within this IPC namespace.__randomize_layout
: This is a marker used in the kernel to indicate that the layout of this structure should be randomized in memory. This is a security feature to prevent certain types of attacks that rely on knowing the memory layout of kernel structures.
Each process sharing the memory segment has a VMA (Virtual Memory Area) that points to the file
structure, which in turn points to the physical pages of the memory-mapped file. We use a struct file *
instead of a direct pointer to the shared memory because we want to utilize the memory-mapped file mechanism.
Utilizing shared memory involves solving a producer-consumer problem. In the context of IPC, the send
and receive
operations can be implemented by addressing the producer-consumer problem within the shared memory.
Message Queue
System calls:
Last updated