Introduction to Linux program design-Message Management
Source: Internet
Author: User
Introduction to Linux programming-Message Management-Linux general technology-Linux programming and kernel information. For details, see the following. Process Communication (IPC) in Linux)
Process Communication (IPC) in Linux)
POSIX unknown semaphores
System V semaphore
System V Message Queue
System V shared memory
1. POSIX unknown semaphores if you have studied the operating system, you must be familiar with PV operations. PV operations are atomic.
Operation, that is, the operation can not be interrupted. within a certain period of time, only one process code can be on the CPU.
Execution. In the system, sometimes in order to smoothly use and protect shared resources, we propose the concept of signals.
We need to use a printer. If two processes are output to the printer at the same time, the final result will be
In order to deal with this situation, the POSIX standard puts forward the concept of famous semaphores and unknown semaphores.
Nux only implements the unknown semaphores. Here we will only introduce the unknown semaphores.
To protect shared resources, so that resources are owned by only one process at a time. Therefore, we can use a signal.
Lamp. When the value of the signal lamp is a value, it indicates that the resource cannot be used at this time. Otherwise, the table> display can be used.
To provide efficiency, the system provides the following functions:
The functions of POSIX's unknown semaphores include the following:
# I nclude
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 lamp and initializes its value as value. pshared, which determines whether the semaphore can be used in several processes.
Inter-process sharing. Currently, Linux does not implement inter-process sharing signals, so this value can only be 0. sem_dest
Roy is used to delete the signal lamp. sem_wait call will block the process until the signal lamp value is greater than 0. This function returns
When the signal is automatically set to the value of the first. sem_post and sem_wait, is to add the signal content together
When the signal is sent to wake up the waiting process... sem_trywait and sem_wait are the same, but not blocked, when the signal light value
If the value is 0, EAGAIN is returned, indicating to retry later. sem_getvalue to get the signal light value.
Because Linux does not support it, we cannot use the source program to explain it.
These functions are quite simple to use. For example, we have a program to print two pages to a system printer.
First, create a traffic signal and set its initial value to 1, indicating that a resource is available. Then, a process calls se
M_wait: because the signal lamp value is 1 at this time, this function returns, the printer starts printing, and the signal lamp
The value is 0. If the second process is to be printed, when sem_wait is called, the resource is unavailable because the traffic signal value is 0.
When the printing of the first process is completed, the value of the sem_post signal is 1.
The system notifies the second process, so the sem_wait of the second process is returned. The second process is printed.
However, we can use threads to solve this problem. We will explain what is a thread later.
Add-lrt to the programs of these functions to connect to the library librt. so.
2. To solve the problem above, we can also use the System V semaphore. Fortunately
The System V semaphore is implemented in Linux, so that we can use an instance to explain the. System V semaphore function.
The number mainly includes the following.
# I nclude
# I nclude
# I nclude
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;/* operations */
Short sem_flg;/* operation flag */
};
The ftok function creates a keyword Based on pathname and proj. semget creates a semaphore. If the semaphore is successfully created, the return value is returned.
The ID of the signal. The key is a keyword. It can be created using ftok or IPC_PRIVATE, indicating that it is selected by the system.
A keyword. nsems indicates the number of signals we have created. semflg is the permission flag created, and we have created
The mark of the file is the same.
Semctl controls semaphores. semid indicates the signal to be operated, semnum indicates the number of signals, and cm
D is the operation command. Two values are often used: SETVAL (set the semaphore value) and IPC_RMID (delete the semaphore ).
Arg is a parameter for cmd.
Semop is a function for signal operations. semid is a signal sign, and spos is an operation array to indicate what to do
Operation. nspos indicates the number of arrays. If sem_op is greater than 0, the Operation adds sem_op to the semaphore value.
And wake up the process waiting for the signal to increase. If it is 0, when the semaphore value is 0, the function returns, otherwise Blocking
The semaphore value is 0. If it is less than 0, the function determines that the semaphore value is added with this negative value. If the result is 0, the system will wake up and wait.
Processes whose semaphores are 0. If the small and 0 functions are blocked. If the semaphores are greater than 0, this value is subtracted from the semaphores and the return value is
..
The following example shows how to use these functions. This program uses standard error output instead of me.
We use a printer.
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# Define PERMS S_IRUSR | S_IWUSR
Void init_semaphore_struct (struct sembuf * sem, int semnum,
Int semop, int semflg)
{
/* Initial traffic 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 program ends. If not, change 1 to 0)
You can use the ipcs command to view the signal lights, and use ipcrm to delete the signal lights
*/
# 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 create a keyword selected by the system */
/* The initial value of the signal lamp after creation is 0 */
If (semid = semget (IPC_PRIVATE, 1, PERMS) =-1)
{
Fprintf (stderr, "[% d]: Acess Semaphore Error: % s \ n \ ",
Getpid (), strerror (errno ));
Exit (1 );
}
/* Semwait requires resource operations (-1 )*/
Init_semaphore_struct (& semwait, 0,-, 0 );
/* Semsignal is the operation to release resources (+ 1 )*/
Init_semaphore_struct (& semsignal, 0, 0 );
/* There is a system resource at the beginning (a standard error output )*/
If (semop (semid, & semsignal, 1) =-1)
{
Fprintf (stderr, "[% d]: Increment Semaphore Error: % s \ n \ ",
Getpid (), strerror (errno ));
If (del_semaphore (semid) =-1)
Fprintf (stderr, "[% d]: Destroy Semaphore Error: % s \ n \ ",
Getpid (), strerror (errno ));
Exit (1 );
}
/* Create a process chain */
For (I = 0; I If (childpid = fork () break;
Sprintf (buffer, "[I = % d] --> [Process = % d] --> [Parent = % d] --> [Child = % d] \ n ",
I, getpid (), getppid (), childpid );
C = buffer;
/* The resource is required to enter the atomic operation */
While (semop_ret = semop (semid, & semwait, 1) =-1) & (errno = EINTR ));
If (semop_ret =-1)
{
Fprintf (stderr, "[% d]: Decrement Semaphore Error: % s \ n \ ",
Getpid (), strerror (errno ));
}
Else
{
While (* c! = '') Fputc (* c ++, stderr );
/* The atomic operation is complete. 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 \ ",
Getpid (), strerror (errno ));
}
/* When we fail to ask the signal lights of other processes, we have deleted the signal lights */
While (wait (& status) =-1) & (errno = EINTR ));
/* The signal light can only be deleted once */
If (I = 1)
If (del_semaphore (semid) =-1)
Fprintf (stderr, "[% d]: Destroy Semaphore Error: % s \ n \ ",
Getpid (), strerror (errno ));
Exit (0 );
}
The main purpose of a traffic signal is to protect critical resources (only owned by one process at a time ).
3. To facilitate inter-process communication, SystemV provides
Some functions are used to implement process communication. This is the message queue.
# I nclude
# I nclude
# I nclude
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 type */
}
The msgget function is the same as the semget function. The flag of a message queue is returned. msgctl and semctl control messages.
... Msgsnd and msgrcv functions are used for message communication. msgid is a message queue sign for receiving or sending.
Msgp is the content accepted or sent. msgsz is the size of the message. The structure msgbuf contains at least one content
Is msgtype. Other components are user-defined. For the sending function msgflg, it indicates the operation when the buffer is used up.
The receiving function indicates the processing when there is no message. Generally, it is 0. The receiving function msgtype indicates the operation when receiving the message.
If msgtype is set to 0, the first message in the message queue is received. If msgtype is set to 0, the Message Type in the message queue is equal to
One message. The minimum number of consumed messages in a received message queue smaller than or equal to the absolute value of msgtype
Information. We use an instance to explain the process communication. The program below consists of a server and a client. Run the service first.
Run the client.
Server. c
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# 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", strerror (errno ));
Exit (1 );
}
If (msgid = msgget (key, PERM | IPC_CREAT | IPC_EXCL) =-1)
{
Fprintf (stderr, "Creat Message Error: % s \ a \ n", strerror (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)
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# 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", strerror (errno ));
Exit (1 );
}
If (msgid = msgget (key, PERM) =-1)
{
Fprintf (stderr, "Creat Message Error: % s \ a \ n", strerror (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 \ n", msg. buffer );
Exit (0 );
}
Note that the Message Queue created by the server is not deleted at the end. You need to use the ipcrm command to delete the message queue.
4. SystemV shared memory another way to communicate with processes is to use the shared memory. SystemV provides the following
Function to implement shared memory.
# I nclude
# I nclude
# I nclude
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 nothing to explain. size is the size of the shared memory. shmat is used to connect to the shared memory.
. Shmdt is used to disconnect the shared memory. Do not be intimidated by the words in the shared memory. The shared memory is easy to implement and
We only need to replace the. shmaddr and shmflg values with 0. Before using a shared memory, we call
Hmat obtains the starting address of the shared memory. After the memory usage ends, we use shmdt to disconnect the memory.
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# I nclude
# 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", strerror (errno ));
Exit (1 );
}
If (fork ())
{
P_addr = shmat (shmid, 0, 0 );
Apsaradb for 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 that writes parameters to the shared memory, and then the child process reads the content. Finally, we need to use the ip address
When crm releases resources, it first finds the ID using ipcs and then deletes it using ipcrm shm ID.
Postscript:
Process Communication (IPC) is the basis of network programs. In many network programs, the concept of Process Communication is widely used.
Communication with the knowledge. In fact, Process Communication is a very complicated task. I will give a brief introduction here. If you want
The best way to learn more about process communication is to constantly write programs and read online manuals.
A lot of knowledge can be referred.
The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion;
products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the
content of the page makes you feel confusing, please write us an email, we will handle the problem
within 5 days after receiving your email.
If you find any instances of plagiarism from the community, please send an email to:
info-contact@alibabacloud.com
and provide relevant evidence. A staff member will contact you within 5 working days.