This article is participating in the topic “Through Linux 30 years” essay activity.

Writing in the front

In this article, I will explain the technique by which some processes communicate with each other under Linux – interprocess communication. Learn about Linux process communication technology!

A signal,

Signals are difficult to understand and serve to inform the receiving process that an event has occurred. Mainly used as a means of synchronization between processes and between different threads of the same process. Signaling is an emulation of the interrupt mechanism at the software level and is the only mechanism for Asynchronous interprocess communication in Linux.

Type of signal

It can be divided into reliable signal and unreliable signal, real-time signal and non-real-time signal. Unreliable signals: Signals whose values are less than SIGRTMIN(SIGRTMIN=32, SIGRTMAX=63) are implemented in the Unix way and are called unreliable signals because they will be lost. The processing mechanism of unreliable signals is similar to that of interrupts. If the same signal occurs several times at the same time, it will be merged into one signal, and other signals will be lost. Unreliable signals have predetermined values, each signal has a defined purpose and meaning, and each signal has its own default action.

Reliable signal: Linux also supports improved reliable signal, the addition of 32 new signals, these signals are reliable signals, performance in the signal support queuing, will not be lost, how many times, you can receive how many times. Signal values in the SIGRTMIN, SIGRTMAX range are reliable signals.

Commonly used functions

There are two signal installation functions: signal() and sigaction(). Signal () takes two arguments. Signum specifies the signal to install, and handler specifies the handler for the signal. The return value of this function is a function pointer to the handler that was installed last time. Sigaction () is commonly used for real-time signals, and it has more options, most importantly the ability to install callbacks with parameters for real-time signals.

There are six signal sending functions: the raise() function is a simple encapsulation of kill and can only send a signal to itself. Abort () encapsulates the SIGABRT signal and can be replaced by the kill() function. Alarm () is designed for SIGALRM and features delayed signal transmission, which can be understood as timer + signal. Setitmer () is a more complex timer that implements not only aperiodic and periodic timers, but also many more timer types. Kill () and sigqueue() are basic signal sending functions. Kill () is used to send signals without arguments, and sigQueue () is used to send signals with arguments.

Shielding signal

A shielded signal is a signal that temporarily blocks its delivery. After the shielding is removed, the signal will be delivered and will not be lost. The related functions are: sigemptyset(), sigismember(), etc. Here we focus on sigprocmask(). The sigprocmask() function can operate on a set of signals based on arguments as follows:

SIG_SETMASK Update process blocking signal set for the set points to mask the entire process signal;

SIG_BLOCK adds a set of signals to the process’s current blocking signal set.

SIG_UNBLOCK If the process blocking signal set contains a signal that the set points to, then unblock the signal.

Second, the pipeline

Pipes are one of the earliest forms of Unix IPC, with named pipes and unnamed pipes

A nameless pipe is a half-duplex communication mode in which data flows only one way and can only be used between parent-child processes. Process relatedness generally refers to the father-child relationship. Anonymous pipes are commonly used for communication between two different processes. When a process creates a pipe and calls fork to create a child of its own, the parent closes the read pipe and the child closes the write pipe, providing a way for data to flow between the two processes. Named pipes are also a half-duplex communication mode, but they allow communication between unrelated processes.

Pipes have the following characteristics: They can only be used between parent and child processes or between sibling processes (related processes);

A separate file system: A pipe is a file for the processes at both ends of the pipe, but it is not a common file. It does not belong to a file system. Instead, it is a separate portal, which forms a file system and exists only in memory.

Data reading and writing: What one process writes to a pipe is read by a process at the other end of the pipe. The written content is added to the end of the pipe buffer each time, and the data is read from the buffer’s head each time.

Pipe functions involved:

#include <unistd.h>
int pipe(int fd[2])
Copy the code

Fd [0] is a read and fd[1] is a write. Therefore, a process that has created a pipe with pipe() typically forks a child process and communicates with the parent process through the pipe.

Third, FIFO

FIFO, also known as named pipes, is characterized by the ability of unrelated processes to exchange data. FIFO provides a pathname associated with it, which exists in the file system as a FIFO file. In this way, even processes that have no parent-child relationship with the creator of the FIFO can communicate with each other through the FIFO as long as they have access to the path.

Int mkfifo(const char * pathname, mode_t mode)

The three interprocess communication modes provided by System V

The message queue

Message queues can be thought of as linked lists of messages stored in the kernel from which processes can read and write data. The advantage of message queues over pipes is that they can exist independently of the sending and receiving processes: a process can write without another process waiting to read. Sending messages also avoids the synchronization and blocking problems of named pipes: one process writes to the message queue and exits, while another process can still open and read the message.

A semaphore

Semaphores are special in that they are counters that provide a mechanism for controlling access to shared resources between processes. It is an in-memory flag that a process can use to determine whether or not it can access some shared resource, and it can also modify this flag. In addition to access control, it can also be used for process synchronization. The workflow is to check the semaphore that controls the resource, and if the semaphore value is greater than 0, the resource is available, and subtract it by 1 to indicate that it is currently in use. If the signal quantum value is 0, the process sleeps until the signal quantum value is greater than 0.

The Shared memory

Shared memory maps a segment of memory that can be accessed by other processes, allowing multiple processes to share a given storage area and access it directly. It is specifically designed for the low efficiency of other inter-process communication methods. It is often used in conjunction with other communication mechanisms, such as semaphores, to achieve synchronization and communication between processes.

The socket

Linux sockets are divided into UNIX domain sockets and network sockets. UNIX domain sockets are similar to sockets, but more efficient because they do not perform protocol processing, such as calculating checksums, sending acknowledgements, and so on. They simply copy data. Network sockets use networks to communicate, and unlike the communication methods mentioned earlier, they can be used for interprocess communication between different computers.

conclusion

The relationship between different communication modes is shown as follows:

It should be noted that soft interrupt signal mechanism can be regarded as a simple and effective way of interprocess communication if the information transmitted is small or some behaviors need to be triggered by signals. However, if the amount of information required to pass between processes is large or there is a requirement to exchange data between processes, then other communication methods need to be considered.

About shared memory: Shared memory communication is achieved by attaching the shared memory buffer directly to the virtual address space of the process. Therefore, synchronization of read and write operations between these processes cannot be achieved by the operating system. Must be resolved by each process using other synchronization tools. And Linux cannot strictly guarantee exclusive access to shared memory blocks, so use caution.