Process Communication under Linux (IPC)
1.posix Named Signal Signal 2.system V Sample 3.System V Message Queue 4.system V Shared Memory
-------------------------------------------------- ------------------------------ 1. POSIX No name signal If you have learned the operating system, then it is sure that PV operations. PV operation is atomic operation. That is, the operation is not interrupted. In a certain period of time, only one process can be executed on the CPU. In the system, sometimes, in order to successfully use and protect the shared resources, everyone puts forward the concept of signal. Suppose we use a printer, if there are two processes at the same time, then the final result will be What is it. In order to deal with this situation, the POSIX standard proposes the concept of a named semaphore and an unnamed signal. Since Linux only implements an unknown semaphore, we just introduce an unnamed signal. The amount of signal is mainly used. To protect shared resources, the resources have only one process at a moment. To this end, we can use a signal. When the value of the signal light is a value, it indicates that the resource cannot be used. Otherwise, Table> You can use it. In order to provide efficiency, the system provides a function of the following function POSIX's unnamed signal volume:
#include
int sem_init (sem_t * sem, int pshared, unsigned int value); int sem_destroy (sem_t * sem); int sem_wait (sem_t * sem); int sem_trywait (sem_t * sem); int sem_post (sem_t * sem); int sem_getvalue ( SEM_T * SEM);
SEM_INIT creates a signal and initializes its value for value.pshared to determine whether the semaphore can be shared between several processes. Since the current Linux has not implemented the inter-process shared signal light, this value can only be taken by 0. SEM_DESTROY is used to delete Signal light. Sem_Wait call will block the process until the value of the signal light is greater than 0. This function is automatically returned, the one. Sem_Post and Sem_Wait of the signal is returned, it is the process of adding the contents of the signal to the signal to wait for the process .. Sem_Trywait and SEM_WAIT, but does not block, return EAGAIN when the value of the signal light is 0, indicating that the re-test. Sem_GetValue get the value of the signal light. Due to Linux does not support, we have no way to explain the source program. These The use of a function is quite simple. For example, we have a program to print two pages to a system printer. We first create a signal light, and make the initial value of 1, indicating that we have a resource available. Then a process call SEM_Wait due to this Time the value of the signal light is 1, so this function returns, the printer starts printing, and the value of the signal light is 0. If the second process is to be printed, when the SEM_WAIT is called, the value of the signal light is 0, the resources are not available, so Block. When the first process print is complete, call the value of the SEM_POST signal light is 1, this time the system notifies the second process, so the second process is returned. The second process starts printing. However, we can Use thread to solve this problem. We will explain what is thread later. Compile the program that contains the above functions to add -lrt to connect librt.so 2. The SYSTEM V signal is to solve the above problem, we can also use the System V signal. Very fortunate is Linux to implement the SYSTEM V signal. This way we can use the instance. System V signal is mainly below several.
#include #include #include
key_t ftok (char * pathname, char proj); int semget (key_t key, int nsems, int semflg); int semctl (int semid, int semnum, int cmd, union semun arg); int semop (int semid, struct sembuf * SPOS, INT NSPOS;
Struct sembuf {short sem_num; / * Use that signal * / short sem_op; / * What operation * / short sem_flg; / * Operation flag * /}; ftok function is based on Pathname and Proj to create a keyword. Semget Create a semaphore. When you return the ID, Key is a keyword, which can be created with ftok can also be IPC_Private indicating that a keyword is made by the system. NSEMS indicates the number of signals we created. Semflg is created The flag is the same as the flag of the file. SemCTL performs a series of controls for the semap. Semid is the signal flag to operate. Semnum is the number of signals, the CMD is an operation command. The two values that are often used are: SetVal (setting the value of the semaphore) .arg is a parameter for cmd. Semop is a function of the signal. SEMID is a signal flag, SPOS is an operator array indicates what operations, Nspos indicate The number of arrays. If the SEM_OP is greater than 0, then the operation adds SEM_OP to the value of the semaphore, and wakes up the process of waiting signal increases. If it is 0, when the value of the signal is 0, the function returns, otherwise it is blocked until The value of the signal is 0. If less than 0, the value determines the value of the signal plus this negative value. If the result is 0 wakes up the process of waiting for the signal amount of 0, if the small and 0 functions are blocked. If it is greater than 0, then from the signal This value is reduced and returned. Let's take a way in one instance. This program uses a standard error output instead of our printer.
#include #include #include #include #include #include #include #include #include #include #include
#define perms s_irusr | S_IWUSR
Void init_semaphore_struct (struct sembuf * sem, int semnum, int semop, int semflg) {/ * initial signal structure * / SEM-> SEM_NUM = SEMNUM; SEM-> SEM_OP = Semop; SEM-> SEM_FLG = SEMFLG;}
INT DEL_SEMAPHORE (INT SEMID) {/ * signal light is not removed with the end of the program, if we don't delete it (change 1 to 0) You can use the IPCS command to see the signal, use IPCRM to delete the signal light * / #IF 1 Return SemctL (SemID, 0, IPC_rmid); #ENDIF}
Int main (int Argc, char ** argv) {char buffer [max_canon], * C; INT i, N; int SemID, Semop_ret, STATUS; PID_T ChildPid; Struct Sembuf Semwait, SemSignal
IF ((argc! = 2) || ((n = atoi (argv [1])) [Process =% D] -> [PARENT =% D] -> [Child =% D] ", I, GetPid (), getppid (), childpid; c = buffer;
/ * Here you request resources, enter atomic operation * / while ((Semop_ret = Semop (SemID, & Semwait, 1)) == - 1) && (Errno == Eintr)); if (Semop_ret == - 1) {FPRINTF (stderr, "[% D]: Decrement Semaphore Error:% sa", getpid (), strerror (errno);} else {while (* c! = ') FPUTC (* C , stderr); / * Atom Operation, hurry up resource * / while ((Semop_ret = Semop (SemID, & SemSignal, 1)) == - 1) && (errno == eintr)); if (Semop_ret == - 1) fprintf (stderr, " [% D]: Increment Semaphore Error:% SA ", getPid (), strrror (errno));} / * When you ask the signal light, we delete the signal * / while ((Wait (& status) = = -1) && (errno == EINTR)); / * The signal light can only be deleted * / if (i == 1) IF (Del_Semaphore (SEMID) == - 1) fprintf (stderr, "[% D ]: Destroy Semaphore Error:% sa ", getpid (), strrror (errno)); exit (0);}
The main purpose of the signal light is to protect critical resources (only by one process is only one process). 3. The Systemv Message Queue For the process of communicating between the processes, we can use pipeline communication SYSTEMV to provide some functions to implement process communication. This is the message queue.
#include #include #include
int msgget (key_t key, int msgflg); int msgsnd (int msgid, struct msgbuf * msgp, int msgsz, int msgflg); int msgrcv (int msgid, struct msgbuf * msgp, int msgsz, long msgtype, int msgflg); int MSGCTL (int MSGID, INT CMD, Struct MSQID_DS * BUF);
Struct msgbuf {long msgtype; / * message type * / ....... / * Other data types * /}
Like the Semget, the Msgget function is returned. Returns a message queue. MSGCTL and SemctL are controlled to messages. The MSGSND and MSGRCV functions are the message queue flag for accepting or sending messages. Msgp is accepting or sent. Content. Msgsz is the size of the message. The contents of the structural msgbuf are at least one for MsgType. Other components are user-defined. For the send function msgflg, the send function MSGFLG indicates the operation of the buffer for use. The accept function indicates whether there is no message. Typically 0. The reception function MsgType indicates the operation of the message. If MSGTYPE = 0, the first message of the message queue is received. It is greater than the 0 reception queue equal to the first message of this value. Small smaller The minimum message in all messages that is equal to the absolute value of the MsgType. We explain the process communication with an instance. Below this program has Server and Client. First run the server, run the client. Server.c
#include #include #include #include #include #include #include #include #include #include #include
#define msg_file "server.c" #define buffer 255 #define perm s_irusr | s_iwusrstruct msgtype {long mtype; char buffer [buffer 1];
INT main () {structure msgtype msg; key_t key; int msgid;
IF ((Key = FTOK (MSG_FILE, 'A')) == - 1) {fprintf (stderr, "creat key error:% sa", strrror (errno)); exit (1);}
IF ((MSGID = Msgget (key, perm | ipc_creat | ipc_excl)) == - 1) {fprintf (stderr, "creat message error:% sa", strrror (errno)); exit (1);}
While (1) {MSGRCV (MSGID, & MSG, SIZEOF (Struct MsgType), 1, 0); FPRINTF (stderr, "server receive:% s", msg.buffer; msg.mtype = 2; msgsnd (MSGID, & MSG SIZEOF (STRUCT MSGTYPE), 0);} exit (0);
-------------------------------------------------- ------------------------------
Client (Client.c)
#include #include #include #include #include #include #include #includde #define msg_file "server.c" #define buffer 255 #define perm s_irusr | s_iwusr
Struct msgtype {long mtype; char buffer [buffer 1];
INT Main (int Argc, char ** argv) {struct msgtype msg; key_t key; int msgid;
IF (argc! = 2) {fprintf (stderr, "usage:% s string a", argv [0]); exit (1);}
IF ((Key = FTOK (MSG_FILE, 'A')) == - 1) {fprintf (stderr, "creat key error:% sa", strrror (errno)); exit (1);}
IF ((msgid = msgget (key, perm)) == - 1) {fprintf (stderr, "creat message error:% sa", strrror (errno)); exit (1);}
Msg.mtype = 1; strncpy (msg.buffer, argv [1], buffer); msgsnd (msgid, & msg, sizeof (struct msgtype), 0); MEMSET (& MSG, '', sizeof (struct msgtype); msgrcv (MSGID, & MSG, SIZEOF (STRUCT MSGTYPE), 2, 0); FPRINTF (Stderr, "Client Receive:% S", Msg.Buffer; EXIT (0);}
Note that the message queue created by the server is finally deleted, we want to use the IPCRM command to delete. 4. The method of SYSTEMV sharing memory has a process communication is to use shared memory .Systemv provides the following functions to implement shared memory. # Include #include #include
int shmget (key_t key, int size, int shmflg); void * shmat (int shmid, const void * shmaddr, int shmflg); int shmdt (const void * shmaddr); int shmctl (int shmid, int cmd, struct shmid_ds * BUF);
SHMGET and SHMCTL have no good explanation. Size is the size of shared memory. SHMAT is used to connect to shared memory. SHMDT is used to disconnect shared memory. Don't be shared by shared memory, sharing memory is actually easy to implement and Used. Shmaddr, Shmflg, we can use 0 to replace. We call Shmat to get the start address of shared memory before using a shared memory. We use ShMDT to disconnect this memory.
#include #include #include #include #include #include #include #include
#define perm s_irusr | S_IWUSR
INT main (int Argc, char ** argv) {
Int ShmId; char * p_addr, * c_addr; if (argc! = 2) {fprintf (stderr, "usage:% s a", argv [0]); exit (1);}
IF ((shmid = shmget (IPC_PRIVATE, 1024, Perm) == - 1) {fprintf (stderr, "create share memory error:% sa", strrror (errno)); exit (1);} if (fork )) {p_addr = shmat (shmid, 0, 0); MEMSET (p_addr, '', 1024); Strncpy (p_addr, argv [1], 1024); exit (0);} else {c_addr = shmat (shmid, 0,0); Printf ("Client Get% S", C_ADDR); exit (0);}}
This program is a parent process writes the parameters to shared memory, then reads the content. Finally, we should use IPCRM to release resources. First use IPCs to find ID and remove it with IPCRM SHM ID. Postscript: Process Communication (IPC) It is the basis of the network program. In a lot of network programs, you will use the concepts and knowledge of the process communication. In fact, the process communication is a very complicated thing. I am just a simple introduction here. If you want to learn the process communication Detailed knowledge, the best way is your constant write procedure and watching the online manual. Now there is a lot of knowledge on the Internet to refer to the reference. Unfortunately, many of me have been prepared in English. If you find Chinese Please tell me as soon as possible. Thank you! "