LINUX C language programming - process communication, message management

xiaoxiao2021-03-06  33

Foreword: Process Communication under Linux (IPC)

Process Communication under Linux (IPC)

1.posix is ​​not named

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> Can be used. In order to provide efficiency, the system provides the following functions.

The function of POSIX's unnamed signal has the following:

#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 are the same, but it is not blocked. When the value of the signal is 0, it returns EAGAIN, indicating that the retest. Sem_GetValue gets the value of the signal light.

Due to Linux does not support, we have no way to explain the source program.

The use of these functions 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 Since this time the value is 1, 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, due to the value of the signal light, the resources are not available. So it blocked. When the first process print is complete, 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 threads to solve this problem. We will explain what threads will be explained later. Compile the program containing 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 SMNUM, INT CMD, Union Semun Arg);

INT Semop (Int Semid, Struct Sembuf * SPOS, INT NSPOS);

Struct sembuf {short sem_num; / * Using that signal * /

Short sem_op; / * What to do * /

Short sem_flg; / * Operation logo * /

}

The FTOK function is based on Pathname and Proj. Semget creates a semaphore. The ID of the signal is returned, and the key is a keyword, which can be created with FTOK can be IPC_Private indicates that a keyword is selected by the system. NSEMS indicates that the number of signals we created. Semflg is the permissions of the created, which is the same as the logo we created a file.

SemCTL performs a series of controls for the semap. Semid is the signal flag to operate, and semnum is the number of signals. The CMD is an operation. The two values ​​that are often used are: setVal (setting the quantity value) and IPC_rmid ( Delete the signal. Theary is a parameter to the CMD.

Semop is a function of the signal. Semid is a signal flag, and the SPOS is an operator array indicates what operations are to do. NSPOS indicate the number of arrays. If the SEM_OP is greater than 0, the operation adds SEM_OP to the value of the semaphore, and Wake up the process of waiting for signals. If 0 If the result is a process of waking up the amount of signal of 0, if the small and 0 function is blocked. If it is greater than 0, then this value is subtracted from the signal amount and returns.

Below we will explain the method of using these functions in one example. This program uses standard error to replace our printer.

#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 SMOP, INT SEMFLG)

{

/ * Infantile signal structure * /

SEM-> SEM_NUM = SEMNUM;

SEM-> SEM_OP = SEMOP;

SEM-> SEM_FLG = SEMFLG;

}

INT DEL_SEMAPHORE (int SEMID)

{

/ * The signal light is not deleted as 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 light, and IPCRM can 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])) <1))

{

FPrintf (stderr, "usage:% s number / n / a", argv [0]);

Exit (1);

}

/ * Use IPC_Private to represent a keyword by the system to create * /

/ * The initial value of the signal light after creating is 0 * /

IF ((SEMID = SEMGET (IPC_Private, 1, Perms) == - 1)

{

FPRINTF (stderr, "[% d]: Acess Semaphore Error:% S / N / A",

getPID (), STRERROR (Errno);

Exit (1);

}

/ * Semwait is the operation of the required resource (-1) * /

INIT_SEMAPHORE_STRUCT (& Semwait, 0, -1, 0);

/ * SemSignal is the operation of the release resource ( 1) * /

INIT_SEMAPHORE_STRUCT (& SemSignal, 0, 1, 0); there is a system resource (a standard error output) * /

IF (SemoP (Semid, & SemSignal, 1) == - 1)

{

FPRINTF (stderr, "[% d]: increment semaphore error:% s / n / a",

getPID (), STRERROR (Errno);

IF (del_semaphore (semid) == - 1)

FPrintf (stderr, "[% d]: destroy semaphore error:% s / n / a",

getPID (), STRERROR (Errno);

Exit (1);

}

/ * Create a process chain * /

For (i = 0; i

IF (ChildPid = for ()) Break;

Sprintf (buffer, "[i =% D] -> [process =% d] -> [parent =% d] -> [child =% d] / n",

I, getPid (), getppid (), childpid;

C = Buffer;

/ * Here you request resources, enter atomic operations * /

While (((Semop_ret = Semop (SemID, & Semwait, 1)) == - 1) && (errno == EINTR));

IF (Semop_ret == - 1)

{

FPRINTF (stderr, "[% d]: Decrement Semaphore Error:% S / N / A",

getPID (), STRERROR (Errno);

}

Else

{

While (* C! = '/ 0') FPUTC (* C , stderr);

/ * Atomic operation is completed, release resources quickly * /

While ((Semop_ret = Semop (SemID, & SemSignal, 1)) == - 1) && (errno == EINTR));

IF (Semop_ret == - 1)

FPRINTF (stderr, "[% d]: increment semaphore error:% s / n / a",

getPID (), STRERROR (Errno);

}

/ * When you ask a signal light in other processes, we delete the signal light * /

While ((& 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:% s / n / a",

getPID (), STRERROR (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 MSGS,

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, receive the first message of the message queue. Glighce the message type in the received queue is equal to the first message of this value. Small than 0 receives the minimum number of all messages in all messages in all messages in the MSGTYPE absolute value We explain the process communication with an example. The program is composed of Server and Client. First run the server, run the client.

Service server.c

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define msg_file "server.c"

#define buffer 255

#define perm s_irusr | S_IWUSR

Struct msgtype {

Long mtype;

CHAR BUFFER [Buffer 1];

}

int main ()

{

Struct MsgType MSG;

Key_t key;

INT MSGID;

IF ((key = ftok (msg_file, 'a') == - 1)

{

FPrintf (stderr, "creat key error:% s / a / n", strrror (errno));

Exit (1);

}

IF ((msgid = msgget (key, perm | ipc_creat | ipc_excl) == - 1)

{

FPrintf (stderr, "creat message error:% s / A / n", strrror (errno));

Exit (1);

}

While (1)

{

MSGRCV (MSGID, & MSG, SIZEOF (STRUCT MSGTYPE), 1, 0);

FPRINTF (stderr, "server receive:% s / n", msg.buffer;

msg.mtype = 2;

Msgsnd (MSGID, & MSG, SIZEOF (STRUCT MSGTYPE), 0);

}

exit (0);

}

-------------------------------------------------- ------------------------------

Client (Client.c)

#include

#include

#include

#include

#include

#include

#include

#include

#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 / n / a", argv [0]);

Exit (1);

}

IF ((key = ftok (msg_file, 'a') == - 1)

{

FPrintf (stderr, "creat key error:% s / a / n", strrror (errno));

Exit (1);

}

IF ((msgid = msgget (key, perm)) == - 1)

{

FPrintf (stderr, "creat message error:% s / A / n", strrror (errno));

Exit (1);

}

Msg.mtype = 1;

Strncpy (msg.buffer, argv [1], buffer;

Msgsnd (MSGID, & MSG, SIZEOF (STRUCT MSGTYPE), 0);

MEMSET (& MSG, '/ 0', SIZEOF (Struct MsgType);

MSGRCV (MSGID, & MSG, SIZEOF (STRUCT MSGTYPE), 2, 0);

FPrintf (stderr, "client receive:% s / n", msg.buffer;

exit (0);

}

Note The message queue created by the server is finally deleted, we want to use the ipCRM command to delete.

4. Systemv Shared Memory There is also a process of communication communication with shared memory .stemv 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 / n / a", argv [0]);

Exit (1);

}

IF ((shmid = shmget (IPC_Private, 1024, Perm) == - 1)

{

FPRINTF (stderr, "create share memory error:% s / n / a", strrror (errno));

Exit (1);

}

IF (fork ())

{

p_addr = shmat (shmid, 0,0);

MEMSET (p_addr, '/ 0', 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 will use IPCRM to release resources. First use IPCs to find ID and remove it with IPCRM SHM ID.

postscript:

Process Communication (IPC) is the basis of the network program, which will use a lot of process communication in many network programs. In fact, the process communication is a very complicated thing. I am just a simple introduction here. If You want to learn the detailed knowledge of the process, the best way is your constant write procedure and watch the online manual. Now there is a lot of knowledge on the Internet to refer to the reference. Unfortunately, many of them are written in English. If you I found a Chinese version, please tell me as soon as possible. Thank you!

转载请注明原文地址:https://www.9cbs.com/read-82292.html

New Post(0)