Inter-process communication (5)

Source: Internet
Author: User
Tags readfile

Inter-process communication (5)

1. Preface all the examples in this article are based on the RHEL6.5 platform. The previous article introduced anonymous pipelines. Click this link.
2. A major restriction for introducing MPs queue applications is that it has no name, so it can only be used for Kinship-related inter-process communication. After a famous MPs Queue (named pipe or FIFO) is proposed, this restriction is overcome. FIFO is different from pipelines in that it provides a path name associated with it and exists in the file system as a FIFO file. In this way, even if there is no kinship with the FIFO creation process, as long as the path can be accessed, it can communicate with each other through FIFO (the process that can access this path and the process that creates the FIFO). Therefore, data can be exchanged through non-FIFO processes. It is worth noting that the first in first out (FIFO) is strictly followed, and data is always returned from the beginning for the read of the pipeline and the first in first out (FIFO, write to them to add the data to the end. They do not support file location operations such as lseek.

In the POSIX standard, FIFO is also known as a famous pipe or named pipe. We know that there is no name for the pipeline in the POSIX standard described above, so its biggest disadvantage is that it can only be used for communications between unrelated processes. The biggest feature of FIFO is that each FIFO has a path name associated with it, which allows any two unrelated processes to communicate through FIFO.

Therefore, FIFO has two features:
** Like pipelines, FIFO only provides half-duplex data communication, that is, only one-way data streams are supported.
** Unlike pipelines, FIFO supports communication between any two processes.

3. mknod Function

<span style="font-family:Arial;font-size:12px;">#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>int mknod(const char *pathname, mode_t mode, dev_t dev);</span>
Usage: mknod pipe name p
4. mkfifo Function
<Span style = "font-family: Arial; font-size: 12px;" >#include <sys/types. h> # include <sys/stat. h> // if the call succeeds, 0 is returned. If the call succeeds,-1 int mkfifo (const char * pathname, mode_t mode) is returned. </span>
How to Use: mkfifo-m permission MPs queue name

Parameter description:
Pathname: a Linux path name. It is a FIFO name. That is, each FIFO corresponds to a path name.
The second parameter is the same as the mode parameter in the open () function for opening a common file. It specifies the File Permission bit. That is, when the FIFO is created, the user's access permission is specified, which has the following values: S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, S_IWOTH.

If the first parameter of mkfifo is an existing path name, The EEXIST error is returned. Therefore, the typical Call code first checks whether the error is returned. if the error is returned, you only need to call the function to open the FIFO. General file I/O functions can be used for FIFO, such as close, read, write, and so on.

The mkfifo function specifies O_CREAT by default. | the O_EXECL method is used to create a FIFO. If the operation is successful, 0 is returned. If the FIFO already exists, the creation fails, and-1 is returned, and errno is set to EEXIST. For other errors, set the response errno value;

After creating a FIFO, it must be opened in read-only or write-only mode. Therefore, you can use the open function or the standard file I/O to open the function, for example, fopen. Because FIFO is half-duplex, it cannot be read and written simultaneously.

In fact, General file I/O functions, such as read, write, close, and unlink, can be used for FIFO. Write operations on pipelines and FIFO will always add data to the end, while read operations on them will always start with data. Therefore, operations on data between pipelines and FIFO are not allowed, therefore, the use of the lseek function in the pipe and FIFO is incorrect and the ESPIPE error is returned.

Generally, mkfifo is used to create a FIFO using mkfifo, call open, open the FIFO using one of the read or write methods, and then perform data communication.
Below is a simple test code for FIFO:

<span style="font-family:Arial;font-size:12px;">#include <iostream>    #include <stdlib.h>#include <unistd.h>  #include <fcntl.h>  #include <errno.h>  #include <string.h>  #include <sys/stat.h>  #include <sys/types.h>    using namespace std;    #define FIFO_PATH "/root/fifo"    int main()  {      if (mkfifo(FIFO_PATH, 0666) < 0 && errno != EEXIST)      {          cout<<"create fifo failed."<<endl;          return -1;      }        if (fork() == 0)      {            int readfd = open(FIFO_PATH, O_RDONLY);          cout<<"child open fifo success."<<endl;            char buf[256];            read(readfd, buf, sizeof(buf));          cout<<"receive message from pipe: "<<buf<<endl;            close(readfd);            exit(0);      }        sleep(3);      int writefd = open(FIFO_PATH, O_WRONLY);      cout<<"parent open fifo success."<<endl;        char *temp = "hello world";      write(writefd, temp, strlen(temp) + 1);        close(writefd);  }</span>
Output:
[Root @ MiWiFi-R 1CM csdnblog] #./a. out
Parent open fifo success.
Child open fifo success.
Receive message from pipe: hello world

As shown in the preceding running results, the read-only open operation of the sub-process blocks the parent process from being open in write mode; this and read and write operations will be introduced in the attributes of the pipeline and FIFO;

The POSIX standard not only specifies support for mkfifo IPC, but also supports mkfifo shell commands. Therefore, UNIX compliant with the POSIX standard contains mkfifo commands to create famous pipelines.

[Root @ MiWiFi-R 1CM csdnblog] # mkfifo unzip otest
[Root @ MiWiFi-R 1CM csdnblog] # echo "hello world"> export otest &
[1] 2726
[Root @ MiWiFi-R 1CM csdnblog] # cat <shortotest
Hello world
[1] + Done echo "hello world"> export otest

Add '&' At the end of the second line to run the process in the background. Because FIFO is opened in write-only mode, it is blocked until FIFO is opened in read-only mode. Therefore, the program must be run as a background program, otherwise, the process will be blocked at the front end and no more input can be made.

5. Differences between mknod and mkfifo

The mknod system calls the file specified by the path parameter. The file type and access permission are determined by the mode parameter.
In many unix versions, there is a C library function mkfifo. Unlike mknod, mkfifo does not require superuser permissions in most cases.
Create a named pipe p1.
# Mkfirst-m 0644 p1
# Mknod p2 p
# Ll

<span style="font-family:Arial;font-size:12px;">#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>main(){    if(mkfifo("p1",0644) < 0)    {        perror("mkfifo");        exit(-1);    }    return;}</span>
6. MPS queue opening rules

A famous Pipeline has one more open operation than the pipeline: open.
In the POSIX standard, both pipelines and FIFO operate through file descriptors. By default, operations on these queues are blocked, of course, you can also set them to make their operations non-blocking. We all know that there are two ways to set a file descriptor to O_NONBLOCK for non-blocking:
-- Specify the O_NONBLOCK flag when calling open. For example:
Int fd = open (FILE_NAME, O_RDONLY | O_NONBLOCK );
-- Use the fcntl file descriptor to control the operation function and enable the O_NONBLOCK flag for an opened descriptor. This method is required for pipelines. Example:
Int flag;
Flag = fcntl (fd, F_GETFL, 0 );
Flag | = O_NONBLOCK;
Fcntl (fd, F_SETFL, flag );

It mainly describes the differences between the pipe and FIFO operations in blocking and non-blocking conditions. This figure is very important for understanding and using pipelines and FIFO.


We can see several rules about the reading and writing of pipelines and FIFO. The main points to note are as follows:
· When the read-only open FIFO mode is used, if the FIFO mode is not open in write-only mode, the operation will be blocked until the FIFO mode is open in write-only mode.
· When the read-only open FIFO mode is used, if the FIFO mode is not read-only, this operation will be blocked until the FIFO mode is read-only.
· Read from an empty pipe or an empty FIFO. If the pipe and FIFO are open for writing, the operation will be blocked until the pipe or FIFO has data, or the pipeline or FIFO is no longer opened in write mode. If the pipe and FIFO are not separated, this operation returns 0;
· Write to the pipeline or FIFO. If the pipeline or FIFO is not read, the kernel generates a SIGPIPE signal. By default, this signal terminates the process.

In addition, the following rules must be specified for pipelines and FIFO:
· If the number of bytes of data requested for write is smaller than or equal to PIPE_BUF (POSIX limit on the size of pipelines and FIFO), The write operation can be atomic. If the number of bytes requested for write is greater than PIPE_BUF, then it cannot be guaranteed.

Therefore, we can see that the atomicity of write is determined by whether the number of bytes written to data is smaller than or equal to PIPE_BUF, and whether it is O_NONBLOCK. The following is the operation result of writing data of different sizes in the case of blocking and non-blocking:

In the case of blocking:
· If the number of write bytes is less than or equal to PIPE_BUF, write will block all data writing and write operations will be atomic.
· If the number of write bytes is greater than PIPE_BUF, write will block writing all data, but the write operation is not atomic, that is, write will be based on the remaining size of the current buffer, write the corresponding number of bytes, and wait for the buffer to be free next time. Other processes may perform write operations in the middle.

In the case of non-blocking:
· If the number of write bytes is smaller than or equal to PIPE_BUF, and the pipe or FIFO has enough space to store the data to be written, all data will be written;
· If the number of write bytes is smaller than or equal to PIPE_BUF, And the MPs queue or FIFO does not have enough space to store the data to be written, the EAGAIN error is returned immediately.
· If the number of write bytes is greater than PIPE_BUF and the pipeline or FIFO has at least 1B space, the kernel writes the corresponding number of bytes and returns the number of written bytes;
· If the number of write bytes is greater than PIPE_BUF and there is no space in the pipeline or FIFO, The EAGAIN error is returned immediately.

Verification of the FIFO open rules (mainly to verify the dependency of write open on read open)

<span style="font-family:Arial;font-size:12px;">#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include <fcntl.h>#define FIFO_SERVER "/tmp/fifoserver"int handle_client(char*);int main(int argc, char** argv){int r_rd;int w_fd;pid_t pid;if ((mkfifo(FIFO_SERVER, O_CREAT | O_EXCL) < 0) && (errno != EEXIST))printf("cannot create fifoserver\n");handle_client(FIFO_SERVER);return 0;}int handle_client(char* arg){int ret;ret = w_open(arg);switch (ret){case 0:{  printf("open %s error\n", arg);  printf("no process has the fifo open for reading\n");  return -1;}case -1:{   printf("something wrong with open the fifo except for ENXIO");   return -1;}case 1:{  printf("open server ok\n");  return 1;}default:{   printf("w_no_r return ----\n");   return 0;}}unlink(FIFO_SERVER);}int w_open(char*arg)//0  open error for no reading//-1 open error for other reasons//1  open ok{if (open(arg, O_WRONLY | O_NONBLOCK, 0) == -1){if (errno == ENXIO){return 0;}elsereturn -1;}return 1;}</span>
Output:
[Root @ MiWiFi-R 1CM csdnblog] #./a. out
Open/tmp/internal oserver error
No process has the fifo open for reading

7. MPS queue read/write rules

Open is enabled through open. It is opened in blocking mode by default. If open specifies O_NONBLOCK, it is opened in non-blocking mode.
The results produced by O_NONBLOCK and O_NDELAY both convert I/O to non-block mode. If no data is read or the write buffer is full, the system will return immediately without shelving the program action, until data or writing is completed.
The difference between them is that the establishment of O_NDELAY will make the I/O function immediately return 0, but another problem arises, because the result returned when the end of the file is read is also 0, in this way, we cannot know what the situation is. Therefore, O_NONBLOCK is generated and will return-1 when data cannot be read and set errno to EAGAIN.
However, in gnu c, O_NDELAY is only used for compatibility with BSD programs. In fact, O_NONBLOCK is used as the macro definition, and O_NONBLOCK is not used in ioctl, you can also set it when you open it.

<Span style = "font-family: Arial; font-size: 12px;" >#include <stdlib. h> # include <stdio. h> # include <unistd. h> # include <sys/stat. h> # include <sys/types. h> # include <fcntl. h> main () {int fd; if (fd = open ("p1", O_RRONLY, 0) <0) // open the MPs queue read-only // if (fd = open ("p1", O_WRONLY, 0) <0) // open the MPs queue only {perror ("open "); exit (-1);} printf ("open fifo p1 for write success! \ N "); close (fd) ;}</span>

Read data from FIFO:
Convention: if a process blocks the access to the FIFO to read data from the FIFO, the read operation in the process is a read operation with a blocking flag.
· If a process writes to enable FIFO and there is no data in the current FIFO, read operations with the blocking mark will be blocked all the time. -1 is returned if no blocking mark is set for the read operation. The current errno value is EAGAIN, prompting you to try again later.
· For read operations with the blocking flag configured, there are two reasons for blocking: data in the current FIFO, but other processes are reading the data. In addition, there is no data in the FIFO. The reason for blocking is that there are new data writes in the FIFO, regardless of the size of the data written to the message or the amount of data requested by the read operation.
· The read blocking mark only applies to the first read operation of the process. If there are multiple read operation sequences in the process, after the first read operation is awakened and the read operation is completed, other read operations to be executed will not be blocked, even if there is no data in the first read operation (in this case, the read operation returns 0 ).
· If no process write is enabled, the read operation with the blocking flag set will be blocked.
NOTE: If data exists in the FIFO, the read operation with the blocking flag is not blocked because the number of bytes in the FIFO is smaller than the number of bytes requested to read, the read operation returns the existing data volume in the FIFO.

Write Data to FIFO:
Convention: if a process blocks the opening of the FIFO to write data to the FIFO, the write operation in the process is a write operation with a blocking flag.
Write operations with blocking flag configured:
· When the data volume to be written is no greater than PIPE_BUF, linux will ensure the atomicity of writing. If the idle buffer of the pipeline is insufficient to accommodate the number of bytes to be written, the system goes to sleep until the buffer can accommodate the number of bytes to be written.
· When the data volume to be written is greater than PIPE_BUF, linux will no longer guarantee the atomicity of writing. As soon as the FIFO buffer has an idle area, the write process will attempt to write data to the pipeline, and the write operation will return after writing all the data written by the request.

For write operations without blocking flag set:
· When the data volume to be written is greater than PIPE_BUF, linux will no longer guarantee the atomicity of writing. After the buffer is fully written into all the FIFO idle buffers, the write operation returns.
· When the data volume to be written is no greater than PIPE_BUF, linux will ensure the atomicity of writing. If the current FIFO idle buffer can accommodate the number of bytes written by the request, the result is returned successfully. If the current FIFO idle buffer cannot accommodate the number of bytes written by the request, the EAGAIN error is returned, remind me to write it later;


Verify the FIFO read/write rules:
The following two read/write programs are provided for FIFO. You can verify the read/write rules by adjusting a few places in the program or using the command line parameters of the program.

# Include <sys/types. h> # include <sys/stat. h> # include <errno. h> # include <fcntl. h> # define FIFO_SERVER "/tmp/fifoserver" int main (int argc, char ** argv) // The parameter is the number of bytes to be written {int fd; char w_buf [4096*2]; int real_wnum; memset (w_buf, 0, 4096*2); if (mkfifo (primary o_server, O_CREAT | O_EXCL) <0) & (errno! = EEXIST) printf ("cannot create external oserver \ n"); if (fd =-1) {if (errno = ENXIO) printf ("open error; no reading process \ n ");} fd = open (export o_server, O_WRONLY | O_NONBLOCK, 0); // set non-blocking flag // fd = open (export o_server, O_WRONLY, 0); // set the blocking flag real_wnum = write (fd, w_buf, 2048); if (real_wnum =-1) {if (errno = EAGAIN) printf ("write to fifo error; try later \ n");} else {printf ("real write num is % d \ n", real_wnum );} real_wnum = write (fd, w_buf, 5000); // 5000 is used to test the non-atomicity when the write bytes are greater than 4096. // real_wnum = write (fd, w_buf, 4096 ); // 4096 is used to test the atomic if (real_wnum =-1) {if (errno = EAGAIN) when the written bytes are not greater than 4096) printf ("try later \ n");} return 0 ;}
Nothing output:

[Root @ MiWiFi-R 1CM csdnblog] #./a. out

// The following program is used with the above program to test the write FIFO rule. The first command line parameter is the number of bytes read from the FIFO request.

<Span style = "font-family: Arial; font-size: 12px;" >#include <sys/types. h> # include <sys/stat. h> # include <errno. h> # include <fcntl. h> # define FIFO_SERVER "/tmp/fifoserver" main (int argc, char ** argv) {char r_buf [4096*2]; int fd; int r_size; int ret_size; r_size = atoi (argv [1]); printf ("requred real read bytes % d \ n", r_size); memset (r_buf, 0, sizeof (r_buf )); fd = open (FIFO_SERVER, O_RDONLY | O_NONBLOCK, 0); // fd = open (FIFO_SERVER, O_RDONLY, 0); // You can compile the read program into two different versions: blocked version and non-blocking version if (fd =-1) {printf ("open % s for read error \ n"); exit () ;}while (1) {memset (r_buf, 0, sizeof (r_buf); ret_size = read (fd, r_buf, r_size); if (ret_size =-1) if (errno = EAGAIN) printf ("no data avlaible \ n"); printf ("real read bytes % d \ n", ret_size); sleep (1);} pause (); unlink (kerbero_server) ;}</span>

Application description:
Compile the read program into two different versions:
· Blocked read version: br
· And non-blocking read version nbr

Compile the write program into two or four versions:
· Non-blocking and the number of bytes written in the request is greater than PIPE_BUF. Version: nbwg
· Non-blocking and the number of bytes written by the request is no greater than PIPE_BUF version: Version nbw
· Blocked and the number of bytes written by the request exceeds PIPE_BUF: bwg
· Blocked and the number of bytes written by the request is no greater than PIPE_BUF version: Version bw
The following describes how to use br, nbr, and w to replace blocking and non-blocking reads in the corresponding program.
Verify the blocking write operation:
1 When the data volume written by the request is greater than PIPE_BUF, it is non-atomic:
Nbr 1000
Bwg

2. atomicity when the data volume written by the request is not greater than PIPE_BUF:
Nbr 1000
Bw

Verify non-blocking write operations:
3 when the data volume written by the request is greater than PIPE_BUF, the non-Atomicity is as follows:
Nbr 1000
Nbwg
4. The data volume written by the request must not exceed the atomicity of PIPE_BUF:
Nbr 1000
Nbw

When the number of bytes written to a request exceeds 4096, the write Atomicity is not guaranteed regardless of whether the blocking mark is set. But there are essential differences between the two:
For blocked write operations, the write operation will wait until all data is written in the idle area of the FIFO, and the data written by the request will eventually be written into the FIFO;
Non-blocking write is returned (the actual number of bytes written) after the Free Zone of the first-in-first-out is fully written. Therefore, some data cannot be written.
The verification of read operations is relatively simple and will not be discussed.

8. Communication Mode

The named pipe provides two basic communication modes: byte mode and message mode. In byte mode, messages flow between the client and the server in the form of a continuous byte stream. This means that for client and server applications, they cannot accurately know how many bytes are read from or written to the pipeline within any specific period of time. Therefore, writing a certain number of bytes on one side does not mean that the other side will read the same number of bytes. In this way, when the client and server transmit data, they do not have to care about the data content. In message mode, the client and server send and receive data through a series of discontinuous data units. Each time a message is sent in the pipeline, it must be read as a complete message.

The biggest feature of the named pipeline is the establishment of a simple client/server program design system. In this architecture, data between the client and the server can be transmitted in one direction or flow in two directions. This is important because we can send and receive data freely, whether the application is a client or a server. The biggest difference between the named MPs Queue Server and the client is that the server is the only process that has the right to create the named MPs queue and can only accept connection requests from the MPs queue client. For a client application, it can only establish connections with a named pipe server. Once a connection is established between a client application and a server application, both processes can read and write data on the MPs queue using the standard Wi n 3 2 function. These include R e a d F I l e and Wr I t e F I l e.

To implement a named pipe server, you must develop an application, create one or more "instances" of the named pipe, and then access them by the client. For the server, an MPS queue instance is actually a handle used to receive a connection request from a local or remote client application. Follow these steps to write a basic server application:
1) Use the API function CreatNamedPipe to create a named pipeline instance handle.
2) use the API function ConnectNamedPipe to listen to client connection requests on the named pipeline instance.
3) use the two a p I functions ReadFile and WriteFile respectively to receive data from the client or send the data to the client.
4) use the API function DisconnectNamedPipe to disable the named pipe connection.
5) use the CloseHandle function to close the handle of the named pipeline instance.

To implement a named pipe client, you must develop an application to establish a connection with a named pipe server. Note that the client cannot create named pipe instances. However, the client can open ready-made instances from the server. The following steps explain how to write a basic client application:
1) Use the API function WaitNamedPipe to wait for a named pipeline instance for your use.
2) use the API function CreatFile to establish a connection with the named pipe.
3) use the API functions WriteFile and ReadFile to send data to or receive data from the server.
4) use the CloseHandle function to close the opened named pipeline session.

9. Restrictions on pipelines and FIFO

The system kernel has the following restrictions on pipelines and FIFO: OPEN_MAX and PIPE_BUF;
OPEN_MAX: Maximum number of descriptors that a process can open at any time.
PIPE_BUF indicates the maximum number of bytes that an MTS queue can write to and from an atom queue. It is not the capacity of an MTS queue or a FIFO queue.

The POSIX standard defines the minimum unchanged values: POSIX_OPEN_MAX and _ POSIX_PIPE_BUF. These two macros are determined by the compilation time defined by the POSXI standard, they are defined by the Standard and will not change. The POSIX standard limits on these two values are:
Cout <_ POSIX_OPEN_MAX <endl;
Cout <_ POSIX_PIPE_BUF <endl;
// The running result is:
20
512

We all know that every constant minimum value of POSIX has a specific system implementation value, which is determined by the specific system, determine the implementation value by calling the following function at runtime:
# Include <unistd. h>
// A specific value is returned for success.-1 is returned for failure.
Long sysconf (int name );
Long fpathconf (int filedes, int name );
Long pathconf (char * path, int name );
Sysconf is used to return system limit values. These values start with _ SC _, and pathconf and fpathconf are used to return the limit values related to files and directories, these values are constants starting with _ pc;
The following is the test code under Linux 2.6.18:
Cout <sysconf (_ SC _OPEN_MAX) <endl;
Cout <pathconf (export o_path, _ PC_PATH_MAX) <endl;

// The running result is:
1024
4096
Of course, the specific implementation values of the above two System Limit values can also be viewed using the ulimit command.
[Root @ idcserver program] # ulimit-
Open File (-n) 1024
Pipe size (512 bytes,-p) 8
These two values are not allowed to be modified in Linux 2.6.18, and therefore do not need to be modified.


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.