UNIX Environment Variables--IPC Pipeline Communication

Pipeline communication uses the first-in-first-out principle for reading and writing, and the lseek function cannot locate the reading and writing position. Pay attention to WeChat official account, codeke resource network

One, unnamed pipe

  An unnamed pipe is a special type of file that is completely managed and maintained by the operating system. Because its storage location is only known by the related processes, it can only be used for communication between the related processes, and its kernel resources will be between two After a communication process exits, it is automatically released. The nameless pipe creation function is:

//from /usr/include/unistd.h
int pipe(int fd[2]);

The function pipe() returns two file descriptors, where fd[0] is used to complete the read operation, and fd[1] is used to complete the write operation. The default blocking mode is.

When reading the pipeline in blocking mode:
(1) There is a reading process, and no writing process:

  1. When there is no data in the pipeline, return immediately
  2. Insufficient data in the pipeline, read all data
  3. Sufficient data in the pipeline, read out the expected data

(2) There is a reading process and a writing process:

  • When there is no data in the pipeline, the reading process is blocked
  • Insufficient data in the pipeline, read all data
  • Sufficient data in the pipeline, read out the expected data

When writing to the pipe in blocking mode:
(1) There is a writing process, but no reading process:

  • The writing process will receive the SIGPIPE signal, and the wirte function will return -1

(2) There is a writing process, a reading process, and there is writing space in the pipeline:

  • Write successfully

In addition, you can use the fcntl() function to use the O_NDELAY or O_NONBLOCK attributes to set the pipeline to non-blocking mode.

 

#include <stdio.h>
FILE * popen(const char *command , const char *type );
int pclose(FILE *stream);

effect:

    The popen function allows a program to start another program as a new process, and can pass data or receive data through it.

    Its internal implementation is to call fork to spawn a child process, execute a shell, and start a process by running a command. This process must be closed by the pclose() function

Parameter Description:

  command: is a pointer to a NULL-terminated shell command string. This command will be passed to bin/sh with the -c flag, and the shell will execute the command.

       type: It can only be one of read or write. If type is "r", the file pointer is connected to the standard output of command; if type is "w", the file pointer is connected to the standard input of command. .

Disadvantages:

    The bad effect of using popen is that for each popen call, not only a requested program must be started, but also a shell must be started. That is, each popen call will start two more processes.

Examples:

#include<stdio.h> 
#include<unistd.h> 
#include<string.h>   
int main() 
{ 
    FILE *fp=NULL; 
    FILE *fh=NULL; 
    char buff[128]={0};   
    memset(buff,0,sizeof(buff)); 
    fp=popen("ls -l","r");//将命令ls-l 通过管道读到fp 
    fh=fopen("shell.c","w+");// 创建一个可写的文件 
    fread(buff,1,127,fp);//将fp的数据流读到buff中 
    fwrite(buff,1,127,fh);//将buff的数据写入fh指向的文件中   
    pclose(fp); 
    fclose(fh);   
    return 0;   
} 

 operation result:

[lol@localhost practice]$ ls
popen popen.c shell.c
[lol@localhost practice]$ cat shell.c
total 12
-rwxrwxr-x. 1 lol lol 5478 May 24 15:39 popen
-rw-rw-r--. 1 lol lol 473 May 24 15:39 popen.c
-rw-rw-r--. 1 lol lol  [lol@localhost practice]$ vim popen.c
[lol@localhost practice]$

Second, the well-known pipeline

A well-known pipe can be created by the mknod command or the function mkfifo(). It can be used to communicate between any two processes in the system, and the created pipe file is stored on the hard disk and will not disappear with the end of the process. mknod is used as follows:

root@wangmumu-virtual-machine:/home/wangmumu/桌面/shares/FIFO# mknod fifo p
root@wangmumu-virtual-machine:/home/wangmumu/桌面/shares/FIFO# ls -l
总用量 24
prw-r--r-- 1 root   root       0  8月 26 00:30 fifo
-rwxr--r-- 1 nobody nogroup  872  8月 25 23:57 fifo_read.c
-rwxr--r-- 1 nobody nogroup  884  8月 25 23:52 fifo_write.c
-rwxr-xr-x 1 root   root    7613  8月 25 23:57 read
-rwxr-xr-x 1 root   root    7651  8月 25 23:52 write

The mkfifo() function is declared as follows:

// from /usr/include/sys/stat.h
int mkfifo(char* path,mode_t mode);

The first parameter of the function is a well-known pipe file. When the function is called, it must not exist. Successful execution returns 0, and failure returns -1.
(1) If the O_NONBLOCK mode is not specified to open (the default), when the process opens the pipeline file in writing or reading, another process must also open the file in the corresponding reading or writing mode, otherwise the process will be blocked In the open() position.

(2) If you specify O_NONBLOCK to open, the read-only open will immediately return 0, but if there is currently no read process open, and the file is opened directly in write mode, open will return -1 and set errno to ENXIO, so it is recommended Generally, the well-known pipe is opened in read mode first.
(3) If both processes have been opened, but a certain process exits in the middle, then:

    The reading process exits, returning the SIGPIPE signal, the
    writing process exits, the reading process will no longer be blocked, and directly returns 0
 

Example:

The following is the implementation of the well-known pipe code. The writing process continuously obtains terminal input and writes to the well-known pipe. The reading process blocks the reading of data in the pipe and prints the data.

Write process code to achieve:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h> 
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "fifo"
int main()
{
    int fd = 0;
    int ret = 0;
    char buffer[1024] = {0};

    if(access(FIFO_NAME,F_OK) == -1)
    {
        ret = mkfifo(FIFO_NAME,0755);
        if(ret != 0)
        {
            printf("mkfifo err!\n");
            return -1;
        }
    }

    printf("mkfifo success,open O_WRONLY!\n");

    fd = open(FIFO_NAME,O_WRONLY);
    if(fd < 0)
    {
        printf("open FIFO_NAME fail!\n");
        return -1;
    }
    else
    {
        while(1)
        {
            gets(buffer);
            //strcpy(buffer,"hello nihao\n");
            ret = write(fd,buffer,strlen(buffer));
            if(-1 == ret )
            {
                printf("write buffer fail!\n");
                return -1;
            }
            memset(buffer,0,sizeof(buffer));
            sleep(1);
        }

    }

    close(fd);
    return 0;
}

Reading process code implementation:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h> 
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#define FIFO_NAME "fifo"
int main()
{
    int fd = 0;
    int ret = 0;
    char buffer[1024] = {0};

    unlink(FIFO_NAME);
    ret = mkfifo(FIFO_NAME,0755);
    if(ret != 0)
    {
        printf("mkfifo err!\n");
        return -1;
    }


    printf("mkfifo success,open O_RDONLY!\n");

    fd = open(FIFO_NAME,O_RDONLY);
    printf("zusissiiii\n");
    if(fd < 0)
    {
        printf("open FIFO_NAME fail!\n");
        return -1;
    }
    else
    {
        while(1)
        {
            ret = read(fd,buffer,sizeof(buffer));
            if(-1 == ret )
            {
                printf("write buffer fail!\n");
                return -1;
            }
            printf("FIFO read buffer:%s\n",buffer);
            memset(buffer,0,sizeof(buffer));
            sleep(1);
        }

    }

    close(fd);
    return 0;
}

Guess you like

Origin blog.csdn.net/Chiang2018/article/details/105470605