One of the fundamental features that makes Linux and other Unices useful is the “pipe”. Pipes allow separate processes to communicate without having been designed explicitly to work together. This allows tools quite narrow in their function to be combined in complex ways.

A simple example of using a pipe is the command:

ls | grep x

When bash examines the command line, it finds the vertical bar character | that separates the two commands. Bash and other shells run both commands, connecting the output of the first to the input of the second. The ls program produces a list of files in the current directory, while the grep program reads the output of ls and prints only those lines containing the letter x.

The above, familiar to most Unix users, is an example of an “unnamed pipe”. The pipe exists only inside the kernel and cannot be accessed by processes that created it, in this case, the bash shell. For those who don't already know, a parent process is the first process started by a program that in turn creates separate child processes that execute the program.

The other sort of pipe is a “named” pipe, which is sometimes called a FIFO. FIFO stands for “First In, First Out” and refers to the property that the order of bytes going in is the same coming out. The “name” of a named pipe is actually a file name within the file system. Pipes are shown by ls as any other file with a couple of differences:

% ls -l fifo1
prw-r--r-- 1 andy users 0 Jan 22 23:11 fifo1|

The p in the leftmost column indicates that fifo1 is a pipe. The rest of the permission bits control who can read or write to the pipe just like a regular file. On systems with a modern ls, the | character at the end of the file name is another clue, and on Linux systems with the color option enabled, fifo| is printed in red by default.

On older Linux systems, named pipes are created by the mknod program, usually located in the /etc directory. On more modern systems, mkfifo is a standard utility. The mkfifo program takes one or more file names as arguments for this task and creates pipes with those names. For example, to create a named pipe with the name pipe1 give the command:

mkfifo pipe

The simplest way to show how named pipes work is with an example. Suppose we've created pipe as shown above. In one virtual console1, type:

ls -l > pipe1

and in another type:

cat < pipe

Voila! The output of the command run on the first console shows up on the second console. Note that the order in which you run the commands doesn't matter.

If you haven't used virtual consoles before, see the article “Keyboards, Consoles and VT Cruising” by John M. Fisk in the November 1996 Linux Journal.

If you watch closely, you'll notice that the first command you run appears to hang. This happens because the other end of the pipe is not yet connected, and so the kernel suspends the first process until the second process opens the pipe. In Unix jargon, the process is said to be “blocked”, since it is waiting for something to happen.

One very useful application of named pipes is to allow totally unrelated programs to communicate with each other. For example, a program that services requests of some sort (print files, access a database) could open the pipe for reading. Then, another process could make a request by opening the pipe and writing a command. That is, the “server” can perform a task on behalf of the “client”. Blocking can also happen if the client isn't writing, or the server isn't reading.

Pipe Madness

Create two named pipes, pipe1 and pipe2. Run the commands:

echo -n x | cat - pipe1 > pipe2 &
cat <pipe2 > pipe1

On screen, it will not appear that anything is happening, but if you run top (a command similar to ps for showing process status), you'll see that both cat programs are running like crazy copying the letter x back and forth in an endless loop.

After you press ctrl-C to get out of the loop, you may receive the message “broken pipe”. This error occurs when a process writing to a pipe when the process reading the pipe closes its end. Since the reader is gone, the data has no place to go. Normally, the writer will finish writing its data and close the pipe. At this point, the reader sees the EOF (end of file) and executes the request.

Whether or not the “broken pipe” message is issued depends on events at the exact instant the ctrl-C is pressed. If the second cat has just read the x, pressing ctrl-C stops the second catpipe1 is closed and the first cat stops quietly, i.e., without a message. On the other hand, if the second cat is waiting for the first to write the x, ctrl-C causes pipe2 to close before the first cat can write to it, and the error message is issued. This sort of random behavior is known as a “race condition”.

Command Substitution

Bash uses named pipes in a really neat way. Recall that when you enclose a command in parenthesis, the command is actually run in a “subshell”; that is, the shell clones itself and the clone interprets the command(s) within the parenthesis. Since the outer shell is running only a single “command”, the output of a complete set of commands can be redirected as a unit. For example, the command:

(ls -l; ls -l) >ls.out

writes two copies of the current directory listing to the file ls.out.

Command substitution occurs when you put a < or > in front of the left parenthesis. For instance, typing the command:

cat <(ls -l)

results in the command ls -l executing in a subshell as usual, but redirects the output to a temporary named pipe, which bash creates, names and later deletes. Therefore, cat has a valid file name to read from, and we see the output of ls -l, taking one more step than usual to do so. Similarly, giving >(commands) results in Bash naming a temporary pipe, which the commands inside the parenthesis read for input.

If you want to see whether two directories contain the same file names, run the single command:

cmp <(ls /dir1) <(ls /dir2)

The compare program cmp will see the names of two files which it will read and compare.

Command substitution also makes the tee command (used to view and save the output of a command) much more useful in that you can cause a single stream of input to be read by multiple readers without resorting to temporary files—bash does all the work for you. The command:

ls | tee >(grep foo | wc >foo.count) \
>(grep bar | wc >bar.count) \
| grep baz | wc >baz.count

counts the number of occurrences of foobar and baz in the output of ls and writes this information to three separate files. Command substitutions can even be nested:

cat <(cat <(cat <(ls -l))))

works as a very roundabout way to list the current directory.

As you can see, while the unnamed pipes allow simple commands to be strung together, named pipes, with a little help from bash, allow whole trees of pipes to be created. The possibilities are limited only by your imagination.

摘抄自: https://www.linuxjournal.com/article/2156

Named Pipe or FIFO with example C program

In computing, a named pipe (also known as a FIFO) is one of the methods for intern-process communication.

  • It is an extension to the traditional pipe concept on Unix. A traditional pipe is “unnamed” and lasts only as long as the process.
  • A named pipe, however, can last as long as the system is up, beyond the life of the process. It can be deleted if no longer used.
  • Usually a named pipe appears as a file, and generally processes attach to it for inter-process communication. A FIFO file is a special kind of file on the local storage which allows two or more processes to communicate with each other by reading/writing to/from this file.
  • A FIFO special file is entered into the filesystem by calling mkfifo() in C. Once we have created a FIFO special file in this way, any process can open it for reading or writing, in the same way as an ordinary file. However, it has to be open at both ends simultaneously before you can proceed to do any input or output operations on it.

Creating a FIFO file
In order to create a FIFO file, a function calls i.e. mkfifo is used.

int mkfifo(const char *pathname, mode_t mode); 
mkfifo() makes a FIFO special file with name pathname. Here mode specifies the FIFO’s permissions. It is modified by the process’s umask in the usual way: the permissions of the created file are (mode & ~umask).

Using FIFO
As named pipe(FIFO) is a kind of file, we can use all the system calls associated with it i.e. openreadwriteclose.

Example Programs to illustrate the named pipe.
There are two programs that use same FIFO. The program 1 writes first, then reads. The program 2 reads first, then writes. They both keep doing it until terminated.

Program 1(Writes first)

// C program to implement one side of FIFO
// This side writes first, then reads
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> int main()
{
int fd; // FIFO file path
char * myfifo = "/tmp/myfifo"; // Creating the named file(FIFO)
// mkfifo(<pathname>, <permission>)
mkfifo(myfifo, ); char arr1[], arr2[];
while ()
{
// Open FIFO for write only
fd = open(myfifo, O_WRONLY); // Take an input arr2ing from user.
// 80 is maximum length
fgets(arr2, , stdin); // Write the input arr2ing on FIFO
// and close it
write(fd, arr2, strlen(arr2)+);
close(fd); // Open FIFO for Read only
fd = open(myfifo, O_RDONLY); // Read from FIFO
read(fd, arr1, sizeof(arr1)); // Print the read message
printf("User2: %s\n", arr1);
close(fd);
}
return ;
}

Program 2(Reads First)

// C program to implement one side of FIFO
// This side reads first, then reads
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> int main()
{
int fd1; // FIFO file path
char * myfifo = "/tmp/myfifo"; // Creating the named file(FIFO)
// mkfifo(<pathname>,<permission>)
mkfifo(myfifo, ); char str1[], str2[];
while ()
{
// First open in read only and read
fd1 = open(myfifo,O_RDONLY);
read(fd1, str1, ); // Print the read string and close
printf("User1: %s\n", str1);
close(fd1); // Now open in write mode and write
// string taken from user.
fd1 = open(myfifo,O_WRONLY);
fgets(str2, , stdin);
write(fd1, str2, strlen(str2)+);
close(fd1);
}
return ;
}


Output: Run the two programs simultaneously on two terminals.

摘抄自:https://www.geeksforgeeks.org/named-pipe-fifo-example-c-program/

进程间通信之数据传输--FIFO的更多相关文章

  1. 进程间通信之数据传输--Socket

    The client server model Most interprocess communication uses the client server model. These terms re ...

  2. 进程间通信和同步:pipe、FIFO、消息队列、信号量、共享内存、信号

    一.半双工管道(pipe) 关于管道详细介绍可参考http://www.cnblogs.com/nufangrensheng/p/3560130.html. 1.管道实现父子进程间通信实例: /* p ...

  3. 查漏补缺:进程间通信(IPC):FIFO

    1.FIFO FIFO,又称命名管道.不同于pipe管道的只能用于拥有共同祖先进程的两个进程间通信,因FIFO通过路径绑定,所以即使是不相关的进程间也可通过FIFO进行数据交换. FIFO是一种文件类 ...

  4. IPC 进程间通信方式——管道

    进程间通信概述 数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间 共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到. 通知时间: ...

  5. Linux学习笔记25——命名管道(FIFO)

    1 命名管道(FIFO) 管道应用的一个重大缺陷就是没有名字,因此只能用于亲缘进程之间的通信.后来从管道为基础提出命名管道(named pipe,FIFO)的概念,该限制得到了克服.FIFO不同于管道 ...

  6. Python::OS 模块 -- 文件和目录操作

    os模块的简介参看 Python::OS 模块 -- 简介 os模块的进程管理 Python::OS 模块 -- 进程管理 os模块的进程参数 Python::OS 模块 -- 进程参数 os模块中包 ...

  7. 开创学习的四核时代-迅为iTOP4412学习开发板

    产品特点: 处理器: Exynos 4412 处理器,Cortex-A9四核,功耗性能俱佳! 性能: 1GB(可选2GB) 双通道 64bit数据总线 DDR3: 4GB(可选16GB)固态硬盘EMM ...

  8. linux服务器开发二(系统编程)--进程相关

    进程相关的概念 程序与进程 程序,是指编译好的二进制文件,在磁盘上,不占用系统资源(CPU.内存.打开的文件.设备.锁等等). 进程,是一个抽象的概念,与操作系统原理联系紧密.进程是活跃的程序,占用系 ...

  9. python OS 模块 文件目录操作

    Python OS 模块 文件目录操作 os模块中包含了一系列文件操作的函数,这里介绍的是一些在Linux平台上应用的文件操作函数.由于Linux是C写的,低层的libc库和系统调用的接口都是C AP ...

随机推荐

  1. ElasticSearch集群状态查看命令大全(转)

    原文地址: https://blog.csdn.net/pilihaotian/article/details/52460747 Elasticsearch中信息很多,同时ES也有很多信息查看命令,可 ...

  2. [转].gitignore文件不起作用的解决方案

    .gitignore文件不起作用的解决方案 觉得有用的话,欢迎一起讨论相互学习~Follow Me 转载地址 https://www.cnblogs.com/liugp/p/10399282.html ...

  3. oracle 统计成绩

    set serveroutput on; declare cursor c1 is select dno,dname from dep; pdno dep.dno%TYPE; pdname dep.d ...

  4. 【翻译】Flink Table Api & SQL — Hive —— Hive 函数

    本文翻译自官网:Hive Functions  https://ci.apache.org/projects/flink/flink-docs-release-1.9/dev/table/hive/h ...

  5. 快速改变文件hash值的方法

    查看哈希值命令 Linux : md5sum + 文件名 $ md5sum .png fe5c3f5ef1d207bc1b646911b463c907 .png Windows : certutil ...

  6. EF Core使用遇到的问题

    目录 EF Core速度问题 问题描述 EF使用方法1,每一行存储一次(400条/s) EF使用方法2,链接不释放 (40条/s) EF使用方法3,多次add,一次SaveChanges(400条/s ...

  7. oracle 解决 exp 空表不能导出的问题

    原因:oralce_11g 中有个新特性,当表无数据时,不分配 segment,以节省空间,这也就导致了 exp 在导出表时,没有数据的表会被忽略 方法一:我们可以向表中插入数据,在删除,这样数据表就 ...

  8. C#使用cmd运行命令并返回控制台输出信息

    public static string RunCmd(string cmd){ cmd = cmd.Trim().TrimEnd('&') + "&exit";/ ...

  9. 定时杀死mysql中sleep的进程

    #!/bin/sh date=`date +%Y%m%d\[%H:%M:%S]` n=`mysqladmin -uroot -p** processlist | grep -i sleep | wc ...

  10. [转帖]亚马逊发布自主64核心ARM处理器:单核性能远超铂金至强

    亚马逊发布自主64核心ARM处理器:单核性能远超铂金至强 https://news.mydrivers.com/1/660/660383.htm 不知道真假 看样子比华为的鲲鹏920 要牛B . 亚马 ...