Inter-process communication (9)

Source: Internet
Author: User

MPs queue

The following is the pipeline implementation file pipe_imp.c, which contains the client and server functions.

Test-pipe implementation header file

1 first is # include:

# Include "cd_data.h"
# Include "cliserv. H"

2. We define some values required by other functions in this file:

Static int server_fd =-1;
Static pid_t mypid = 0;
Static char client_pipe_name [path_max + 1] = {'/0 '};
Static int client_fd =-1;
Static int client_write_fd =-1;

Server Functions

Next we need to discuss server-side functions. The experiment section below shows us the functions for opening and closing famous pipelines and reading messages from clients. The second test section shows the code for opening, sending, and closing the client pipeline. The client pipeline is based on the process ID.

Test-Server Functions

1 server_starting routine creates a famous Pipeline in which the server reads commands. Open the MPs queue to read data. The open operation will be blocked until a client opens the pipeline for writing. We use blocking mode, so that the server can execute blocking reading on the pipeline while waiting for the command sent to him.

Int server_starting (void)
{
# If debug_trace
Printf ("% d:-server_starting ()/n", getpid ());
# Endif
Unlink (server_pipe );
If (mkfifo (server_pipe, 0777) =-1 ){
Fprintf (stderr, "server startup error, no FIFO created/N ");
Return (0 );
}
If (server_fd = open (server_pipe, o_rdonly) =-1 ){
If (errno = eintr) Return (0 );
Fprintf (stderr, "server startup error, no FIFO opened/N ");
Return (0 );
}
Return (1 );
}

2. When the server ends, it removes the famous pipe and the client can detect that no server is running.

Void server_ending (void)
{
# If debug_trace
Printf ("% d:-server_ending ()/n", getpid ());
# Endif
(Void) Close (server_fd );
(Void) unlink (server_pipe );
}

4 The read_request_from_client function shown in the following code blocks reading from the server pipeline until a client writes messages to it:

Int read_request_from_client (message_db_t * rec_ptr)
{
Int return_code = 0;
Int read_bytes;
# If debug_trace
Printf ("% d:-read_request_from_client ()/n", getpid ());
# Endif
If (server_fd! =-1 ){
Read_bytes = read (server_fd, rec_ptr, sizeof (* rec_ptr ));
...
}
Return (return_code );
}

4. If no client opens the pipeline for writing, the read operation returns 0; that is, the client detects the EOF. Then the server closes the MPs queue and re-opens the MPs queue, blocking it before the client opens the MPs queue. This is similar to the first time the server was started; we have reinitialized the server. Insert the following code into the previous function:

If (read_bytes = 0 ){
(Void) Close (server_fd );
If (server_fd = open (server_pipe, o_rdonly) =-1 ){
If (errno! = Eintr ){
Fprintf (stderr, "server error, FIFO open failed/N ");
}
Return (0 );
}
Read_bytes = read (server_fd, rec_ptr, sizeof (* rec_ptr ));
}
If (read_bytes = sizeof (* rec_ptr) return_code = 1;

The server is a single process and may serve multiple clients at the same time. Because each client uses a different pipeline to receive its response, the server needs to write different pipelines to send a response to different clients. Because file descriptors restrict resources, the server opens the client pipeline for writing only when there is data to be sent.

We will open, write and close the client pipeline into three independent functions. This is what we need to do when we want to return multiple results to the search, so that we can create a pipeline once, write multiple responses, and then close the pipeline.

Test-building pipelines

1. First, open the customer pipeline:

Int start_resp_to_client (const message_db_t mess_to_send)
{
# If debug_trace
Printf ("% d:-start_resp_to_client ()/n", getpid ());
# Endif
(Void) sprintf (client_pipe_name, client_pipe, mess_to_send.client_pid );
If (client_fd = open (client_pipe_name, o_wronly) =-1) Return (0 );
Return (1 );
}

2. messages are sent by calling this function. We will take a look at the corresponding client functions later.

Int send_resp_to_client (const message_db_t mess_to_send)
{
Int write_bytes;
# If debug_trace
Printf ("% d:-send_resp_to_client ()/n", getpid ());
# Endif
If (client_fd =-1) Return (0 );
Write_bytes = write (client_fd, & mess_to_send, sizeof (mess_to_send ));
If (write_bytes! = Sizeof (mess_to_send) Return (0 );
Return (1 );
}

3. Close the client pipeline:

Void end_resp_to_client (void)
{
# If debug_trace
Printf ("% d:-end_resp_to_client ()/n", getpid ());
# Endif
If (client_fd! =-1 ){
(Void) Close (client_fd );
Client_fd =-1;
}
}

Client Functions

The client function in pipe_imp.c is used to fill the server. They are very similar to server functions. The difference is the send_mess_to_server function.

Test-client functions

1. After detecting that the server is accessible, the client_starting function initializes the client pipeline:

Int client_starting (void)
{
# If debug_trace
Printf ("% d:-client_starting/N", getpid ());
# Endif
Mypid = getpid ();
If (server_fd = open (server_pipe, o_wronly) =-1 ){
Fprintf (stderr, "server not running/N ");
Return (0 );
}
(Void) sprintf (client_pipe_name, client_pipe, mypid );
(Void) unlink (client_pipe_name );
If (mkfifo (client_pipe_name, 0777) =-1 ){
Fprintf (stderr, "unable to create client pipe % s/n ",
Client_pipe_name );
Return (0 );
}
Return (1 );
}

2. The client_ending function closes the file descriptor and deletes extra famous pipelines:

Void client_ending (void)
{
# If debug_trace
Printf ("% d:-client_ending ()/n", getpid ());
# Endif
If (client_write_fd! =-1) (void) Close (client_write_fd );
If (client_fd! =-1) (void) Close (client_fd );
If (server_fd! =-1) (void) Close (server_fd );
(Void) unlink (client_pipe_name );
}

3 The send_mess_to_server function sends a request through the server pipeline:

Int send_mess_to_server (message_db_t mess_to_send)
{
Int write_bytes;
# If debug_trace
Printf ("% d:-send_mess_to_server ()/n", getpid ());
# Endif
If (server_fd =-1) Return (0 );
Mess_to_send.client_pid = mypid;
Write_bytes = write (server_fd, & mess_to_send, sizeof (mess_to_send ));
If (write_bytes! = Sizeof (mess_to_send) Return (0 );
Return (1 );
}

Similar to the server-side functions we saw earlier, the client uses three functions to get the returned results from the server.

Test-Get server results

1. This client function is used to listen to the server response. He uses read-only mode to open a client pipeline and then responds to this pipeline file as write-only mode.

Int start_resp_from_server (void)
{
# If debug_trace
Printf ("% d:-start_resp_from_server ()/n", getpid ());
# Endif
If (client_pipe_name [0] = '/0') Return (0 );
If (client_fd! =-1) Return (1 );
Client_fd = open (client_pipe_name, o_rdonly );
If (client_fd! =-1 ){
Client_write_fd = open (client_pipe_name, o_wronly );
If (client_write_fd! =-1) Return (1 );
(Void) Close (client_fd );
Client_fd =-1;
}
Return (0 );
}

2. The following are the main read operations performed by the server to obtain matching database records:

Int read_resp_from_server (message_db_t * rec_ptr)
{
Int read_bytes;
Int return_code = 0;
# If debug_trace
Printf ("% d:-read_resp_from_server ()/n", getpid ());
# Endif
If (! Rec_ptr) Return (0 );
If (client_fd =-1) Return (0 );
Read_bytes = read (client_fd, rec_ptr, sizeof (* rec_ptr ));
If (read_bytes = sizeof (* rec_ptr) return_code = 1;
Return (return_code );
}

3. The following client functions identify the end of the server response:

Void end_resp_from_server (void)
{
# If debug_trace
Printf ("% d:-end_resp_from_server ()/n", getpid ());
# Endif
/* This function is empty in the pipe implementation */
}

Working Principle

Client open operations used for writing in start_resp_from_server:

Client_write_fd = open (client_pipe_name, o_wronly );

It is used to prevent the competition conditions caused by the need for the server to quickly respond to multiple client requests.

To explain this in detail, consider the following event sequence:

1. The client sends a request to the server.
2. The server reads the request, opens the client pipeline and sends a response, but is suspended before closing the client.
3. Open the client's MPs queue for reading, read the first response, and close the MPs queue.
4. Then the client sends a new command and opens the client pipeline for reading.
5. The server continues to run and closes its client pipeline.

Unfortunately, at this time, the client is trying to read the pipeline and find the response to its next request, but the read operation returns 0 bytes, because there is no process for the client to open for writing.

We can avoid this competition by allowing customers to open their pipelines for reading and writing, removing the need to re-open the pipeline again. Note that the client does not write data to the MPs queue, so there is no risk of junk data.

Summary

Now we divide our CD database program into two parts: client and server, so that we can develop the user interface and underlying database technology independently. We can see that a well-defined database interface can make full use of computer resources for every major element of the program. If we are more in-depth, we can change the pipeline implementation to the network implementation and use a database server. We will learn more about the network in Chapter 15th.

Summary

In this chapter, we learned how to use pipelines between processes to transmit data. First, we learned about the unknown pipeline, and used the popen and pipe call to create it. Then we discussed how to use the pipeline and DUP call, we can pass data from one program to another standard input. Then we learned about the famous Pipeline and how to transmit data between unrelated programs. Finally, we have implemented a simple client/server example. What is provided to us using FIFO is not only synchronous processing, but also bidirectional data streams.

Contact Us

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.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.