There are multiple communication methods between processes, including pipelines, FIFO, message queues, shared memory, and semaphores.
1. Half Duplex Pipe
This method can only be used between processes with common ancestor. Generally, a pipeline is created by a process, and then the process creates a sub-process through the fork function. Therefore, the pipeline can be applied between parent and child processes as the communication mode between parent and child processes.
Function pipe:
# Include <unistd. h>IntPipe (IntFileds [2]);
The fileds parameter returns two file descriptors: filefds [0] is read and fileds [1] is write, the output of fileds [1] is used as the input of fileds [0. :
Figure 1 half-duplex pipeline in a single process
When one end of the MPs queue is closed, the following two rules apply:(MAN 7 pipe ):
- When a write end has been closed, when all data is read, read returns 0 to indicate that the end of the file has been reached;
- When writing a read-end closed pipeline, the sigpipe signal is generated. If this signal is ignored or captured and processedProgramIf yes, write returns-1 and errno is set to epipe;
When writing a pipeline (or FIFO), the constant pipe_buf specifies the size of the pipeline buffer in the kernel. If the data volume of the MPs queue is smaller than or equal to pipe_buf, the data volume is not interspersed with write operations of the same MPs Queue (or FIFO) with other processes. If multiple processes write one pipe (or FIFO) at the same time and the data exceeds pipe_buf, insertion may occur.
2. FIFO
FIFO is a file type. The st_mode encoding of the stat structure member indicates whether the file is of the FIFO type. You can use the s_isfifo macro to test the file.
Create a FIFO using the mkfifo function:
# Include <sys/types. h># Include<Sys/STAT. h>IntMkfifo (Const Char* Pathname, mode_t mode );
Pathname is used as the name of the FIFO file, and mode specifies the permission of the FIFO file.
3. Basic IPC knowledge
IPC includes message queues, semaphores, and shared memory storage areas. In the kernel, each IPC structure is identified or referenced with a non-negative integer identifier. An identifier exists as an internal name, while a key value acts as an external name, allowing multiple processes to operate on one IPC object. Therefore, whenever you create an IPC structure (call msgget, semget, or shmget), you must specify a key with the Data Type key_t.
There are multiple ways to make the customer process and the server process in the same structure and:
(1) The server process can specify the ipc_private key to create a new IPC structure. The returned identifier is stored somewhere (such as a file) for use by the client process. The key ipc_private ensures that the server process creates a new IPC structure.
Disadvantages of this method: the server process needs to write the integer identifier to the file, and then the customer process needs to read the file to obtain the identifier.
(2) define a key recognized by both the client process and the server process in a public header file. Then, the server process specifies this key to create a new IPC structure.
Problem with this method: if the key has been combined with an IPC structure, the get function (msgget, semget, or shmget) returns an error. Therefore, the server needs to delete the existing IPC structure and try to create the key again.
(3) The customer process and server process recognize a path name and Project ID (the project ID is 0 ~ And then call the ftok function to convert the two values into a key, and then use this key in method (2.
The unique service provided by the ftok function: A path name and a Project ID generate a key..
# Include <sys/IPC. h>Key_t ftok (Const Char* Path,IntID );
The path parameter must reference an existing file. When a key is generated, only eight lower bits of the ID parameter are used.
If one of the following conditions is met, a new IPC structure is created:
- The key is ipc_private;
- The key is not currently combined with the IPC structure of a specific type, and the ipc_creat bit is specified in the flag;
An ipc_perm structure is set for each IPC structure, which specifies the permission and owner information.
Note the following when using IPC:
- The IPC structure works within the system, with no access count;
- The IPC structure has no name in the file system.
4. Message Queue
A message queue is actually a connection table of messages, which is stored in the kernel and identified by the Message Queue identifier.
Function msgget (): Create a message queue or open an existing queue.
# Include <sys/msg. h>IntMsgget (key_t key,IntFlag );//Message Queue ID is returned. If an error occurs,-1 is returned.
Function msgsnd (): Insert the new message to the end of the queue. Each message contains a positive and long integer type field, a non-negative length, and actual data bytes. After successful addition, information in the msqid_ds structure will be updated.
# Include <sys/msg. h>IntMsgsnd (IntMsqid,Void* PTR, size_t nbytes,IntFlag );//If the request is successful, 0 is returned. If an error occurs,-1 is returned.
PTR points to a struct containing the type field and data field, for example:
StructMymsg {LongMtype;//Positive message typeCharMtext [512];//Message data. Of Length nbytes};
Function msgrcv (): Extract messages from a specified queue.
# Include <sys/msg. h>Ssize_t msgrcv (IntMsqid,Void* PTR, size_t nbytes,LongType,IntFlag );//If the message succeeds, the length of the message data is returned. If an error occurs, the value-1 is returned.
When extracting a message, different messages are extracted based on different type values:
- Type = 0: return the first message in the message queue;
- Type> 0: return the first message whose message type is type in the queue;
- Type <0: return the message whose type is smaller than or equal to the absolute value of type in the queue. If there are multiple such messages, the minimum untyped messages are returned.
Function msgctl (): Used to perform multiple operations on the message queue.
# Include <sys/msg. h>IntMsgctl (IntMsqid,IntCMD,StructMsqid_ds *Buf );//If the request succeeds, 0 is returned. If the request fails,-1 is returned.
The cmd parameter in this function specifies the command to be executed on the msqid queue:
- Ipc_stat: The msqid_ds structure of the Message Queue identified by msqid, and put it into the memory referred to by BUF;
- Ipc_set: Set the msqid_ds structure of the Message Queue identified by msqid to the new data directed by the Buf;
- Ipc_rmid: removes the Message Queue from the system and all data in the queue.
5. semaphores
Semaphores (semid_ds in the kernel) are a counter used by multiple processes to control access to shared data objects. To obtain shared resources, the process must perform the following operations:
- Testing and controlling the semaphores of resources;
- If the semaphore value is positive, the process can use the resource. The process reduces the semaphores by 1, indicating that it uses a resource unit;
- If the semaphore value is 0, the process enters the sleep state until the semaphore is greater than 0. After a process is awakened, it returns to the start stage.
Function semget (): Obtain a semaphore ID.
# Include <sys/SEM. h>IntSemget (key_t key,IntNsems,IntFlag );//If the request succeeds, the semaphore ID is returned. If an error occurs, the return value is-1.
The nsems parameter indicates the number of semaphores in the set. If a new semaphore is created, nsems> 0. If an existing semaphore is referenced, The nsems value is set to 0.
Function semop (): Automatically execute the semoparray array command on the semaphore set.
# Include <sys/SEM. h>IntSemop (IntSemid,StructSembuf semoparray [], size_t NOPs );//If the request succeeds, 0 is returned. If the request fails,-1 is returned.
Here, the struct sembuf:
StructSembuf {unsignedShortSem_num;//Member # In SetShortSem_op;//Operation (negative, 0, positve)ShortSem_flg;//Ipc_nowait, sem_undo};
The operations performed by the semop function are mainly performed based on the value of sem_op:
- Sem_op> 0: Number of resources occupied by the process release. The sem_op value is added to the semaphore value. If the Undo flag is specified, sem_op is also subtracted from the signal adjustment of the process;
- Sem_op <0: The process needs to obtain the resources controlled by the semaphore.
(1) If the value of the signal is greater than or equal to the absolute value of sem_op (Resources meet the demand), the absolute value of sem_op is subtracted from the semaphore. If the Undo flag is specified, the absolute value of sem_op is added to the adjusted value of this semaphore of the process;
(2) If the semaphore is smaller than the absolute value of sem_op (the amount of resources cannot meet the demand), then:
(A) If ipc_nowait is specified, semop fails and eagain is returned;
(B) If ipc_nowait is not specified, semncnt plus 1 (because the calling process enters sleep state) in the semid_ds structure of the semaphore, and then the calling process is suspended until one of the following events occurs:
(I) The semaphores must be greater than or equal to the absolute value of sem_op and wake up the calling process;
(Ii) this signal is deleted from the system. In this case, the function fails and eidrm is returned;
(Iii) The process captures a signal and returns it from the signal processing program. In this case, semncnt of the semaphore is reduced by 1, and eintr is returned if a function error occurs.
- Sem_op = 0: indicates that the calling process wants to wait until the semaphore changes to 0. In this case, the processing method is the same as that of sem_op> 0, but the condition is changed to sem_op = 0.
Function semctl (): Contains a variety of operations on semaphores.
# Include <sys/SEM. h>IntSemctl (IntSemid,IntSemnum,IntCMD ,.../*Union semun ARG*/);//Return Value Reference Manual (man 2 semctl ).
The Common commands of this function are the same as those in message queue: ipc_stat, ipc_set, and ipc_rmid. The last parameter is an optional parameter with the semun type. It is a combination of multiple specific command parameters.
Union semun {IntVal;//For setvalStructSemid_ds * Buf;//For ipc_stat and ipc_setUnsignedShort* Array;//For getall and setall};
6. shared storage Zone
A shared storage zone allows two or more processes to share a given storage zone. When a shared storage area is used, semaphores or locks are used to control synchronous access between multiple processes to a given storage area. The kernel sets a shmid_ds struct for each shared storage zone.
Function shmget (): Create a shared storage area identifier.
# Include <sys/SHM. h>IntShmget (key_t key, size_t size,IntFlag );//If successful, the ID of the shared storage area is returned. If an error occurs, the value-1 is returned.
The size is the length of the common storage area. Generally, the size is rounded up to an integer multiple of the system page length. If you are creating a new storage area, you must specify the size. If you are referencing an existing storage area, the size value is 0.
Function shmctl (): Perform multiple operations on the shared storage area.
# Include <sys/SHM. h>IntShmctl (IntShmid,IntCMD,StructShmid_ds *Buf );//If the request succeeds, 0 is returned. If the request fails,-1 is returned.
Among them, the CMD parameters are commonly used: ipc_stat, ipc_set, ipc_rmid. The remaining commands are specific to various systems. Please refer to the reference book (man 2 shmctl in Linux ).
Function shmat (): Connect the created shared storage area to the address space of the calling process.
# Include <sys/SHM. h>Int* Shmat (IntShmid,Const Void* ADDR,IntFlag );//If the operation succeeds, the pointer to the shared storage area is returned. If an error occurs,-1 is returned.
Function shmdt (): Disconnects the shared storage zone from the connection address. Note: This operation does not delete the identifier of the shared storage area and its data structure. This identifier still exists until you call shmctl (shmid, ipc_rmid, null) to delete it.
# Include <sys/SHM. h>IntShmdt (Void*ADDR );//If the request is successful, 0 is returned. If an error occurs,-1 is returned.
7. UNIX domain socket
UNIX domain socket is used for communication between processes running on the same machine. UNIX domain sockets only copy data. They do not execute protocol processing, do not need to add or delete network headers, do not need to calculate the checksum, do not need to generate a sequence number, do not need to send a validation message.
The Unix-domain socket provides two interfaces: stream and datagram. the Unix-domain datagram service is reliable, so no messages are lost or errors are transmitted. A Unix domain socket is a mixture of sockets and pipelines.
When you create a named, interconnected UNIX socket:
- Use the network-oriented Unix domain socket interface;
- Use the socketpair function. This function only supports af_unix fields;
# Include <sys/types. h># Include<Sys/socket. h>IntSocketpair (IntDomain,IntType,IntProtocol,IntSockfd [2]);//If the request succeeds, 0 is returned. If the request fails,-1 is returned.