2024年3月7日发(作者:)

轻松入门实战应用从项目开发角度为你搭建完整的知识体系 wangbaoming
linux管道-应用编程-专题讲座
written by 王保明
linux管道基本概念
1管道基本概念及操作
管道基本概念
管道是Unix中最古老的进程间通信的形式。
我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”
比如:eg: ls | wc -l ps –u wbm01|grep “aa”
管道的本质====》固定大小的内核缓冲区
管道限制
管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道
只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。
匿名管道pipe
包含头文件
功能:创建一无名管道
原型
int pipe(int fd[2]);
参数
fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
返回值:成功返回0,失败返回错误代码
管道创建后示意图
轻松入门实战应用从项目开发角度为你搭建完整的知识体系 wangbaoming
管道基本编程示例
2管道和文件描述符在一起
管道命令的编程实现:
ls | wc –w
文件描述符的深入理解
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERR_EXIT(m)
do
{
perror(m);
exit(EXIT_FAILURE);
} while(0)
int main21(void )
{
int pipefd[2];
pid_t pid;
if (pipe(pipefd) == -1 )
{
printf("pipe() ");
return -1;
}
pid = fork();
if (pid == -1)
{
printf("");
return -1;
轻松入门实战应用从项目开发角度为你搭建完整的知识体系 wangbaoming
}
if (pid == 0)
{
close(pipefd[0]);
//复制文件描述符pipefd[1],给标准输出,言外之意:execlp的ls命令输出到管道中
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[1]);
execlp("ls", "ls", NULL);
//如果替换新的进程印象失败,则会执行下面一句话
sprintf(stderr, "execute the cmd ");
exit(0);
}
else if (pid > 0 )
{
int len = 0;
char buf[100] = {0};
close(pipefd[1]);
//复制文件描述符pipefd[0],给标准输入,言外之意:execlp的wc命令从管道中读
dup2(pipefd[0], STDIN_FILENO);
close(pipefd[0]);
//len = read(pipefd[0], buf, 100);
execlp("wc", "wc", "-w", NULL);
printf("len:%d, buf:%s n", len , buf);
//close(pipefd[0]);
}
wait(NULL);
printf("parent ..quitn");
return 0;
}
int main(int argc, char *argv[])
{
close(0); //关闭表示输入
open("makefile", O_RDONLY); //makefile文件变成标准输入
close(1);//关闭标准输出
open("makefile2", O_WRONLY | O_CREAT | O_TRUNC, 0644); //maifle2变成标准输出
轻松入门实战应用从项目开发角度为你搭建完整的知识体系 wangbaoming
}
execlp("cat", "cat", NULL); //替换进程印象后,执行cat命令
//cat命名从标准输入中按行读,紧接着写到标准输出
return 0;
2管道的读写规则
管道读写规则研究(重点)
当没有数据可读时
O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止。
O_NONBLOCK enable:read调用返回-1,errno值为EAGAIN。
当管道满的时候
O_NONBLOCK disable: write调用阻塞,直到有进程读走数据
O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
当管道不停的被写,写满的时候
O_NONBLOCK disable: write调用阻塞
O_NONBLOCK enable:调用返回-1,errno值为EAGAIN
如果所有管道写端对应的文件描述符被关闭,则read返回0
如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE
当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。
测试管道读(阻塞、非阻塞)
测试管道两端读、写均关闭
测试管道容量
编程实践
man fctl
File descriptor flags
The following commands manipulate the flags associated with a file descriptor.
Currently, only one such
flag is defined: FD_CLOEXEC, the close-on-exec flag. If the FD_CLOEXEC bit is 0, the file
descriptor will
remain open across an execve(2), otherwise it will be closed.
F_GETFD
Read the file descriptor flags.
F_SETFD
轻松入门实战应用从项目开发角度为你搭建完整的知识体系 wangbaoming
Set the file descriptor flags to the value specified by arg.
File status flags
Each open file description has certain associated status flags, initialized by open(2) and
possibly modified
by fcntl(2). Duplicated file descriptors (made with dup(), fcntl(F_DUPFD), fork(), etc.)
refer to the same
open file description, and thus share the same file status flags.
The file status flags and their semantics are described in open(2).
F_GETFL
Read the file status flags.
F_SETFL
Set the file status flags to the value specified by arg. File access
mode (O_RDONLY, O_WRONLY,
O_RDWR) and file creation flags (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC)
in arg are ignored. On
Linux this command can only change the O_APPEND, O_ASYNC, O_DIRECT,
O_NOATIME, and O_NONBLOCK flags.
容量查询
man -6 pipe
Pipe Capacity
A pipe has a limited capacity. If the pipe is full, then a write(2) will block or
fail, depending on
whether the O_NONBLOCK flag is set (see below). Different implementations
have different limits for the
pipe capacity. Applications should not rely on a particular capacity: an application
should be designed so
that a reading process consumes data as soon as it is available, so that a writing
process does not remain
blocked.
In Linux versions before 2.6.11, the capacity of a pipe was the same as the system page
size (e.g., 4096
bytes on x86). Since Linux 2.6.11, the pipe capacity is 65536 bytes.
读写规则
man -6 pipe
If all file descriptors referring to the write end of a pipe have been closed, then an
attempt to read(2)
from the pipe will see end-of-file (read(2) will return 0). If all file descriptors referring
轻松入门实战应用从项目开发角度为你搭建完整的知识体系 wangbaoming
to the read
end of a pipe have been closed, then a write(2) will cause a SIGPIPE signal to be
generated for the calling
process. If the calling process is ignoring this signal, then write(2) fails with the
error EPIPE. An
application that uses pipe(2) and fork(2) should use suitable close(2) calls to close
unnecessary duplicate
file descriptors; this ensures that end-of-file and SIGPIPE/EPIPE are delivered when
appropriate.
It is not possible to apply lseek(2) to a pipe.
#include
PIPE_BUF
[root@localhost ~]# find / -name "limits.h"
/usr/include/linux/limits.h
[root@localhost ~]# find / -name "limits.h" | cat
[root@localhost ~]# find / -name "limits.h" | sed -n "1p"
[root@localhost ~]# cat /usr/include/linux/limits.h
#ifndef _LINUX_LIMITS_H
#define _LINUX_LIMITS_H
#define NR_OPEN 1024
#define NGROUPS_MAX 65536 /* supplemental group IDs are available */
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
#define CHILD_MAX 999 /* no limit :-) */
#define OPEN_MAX 256 /* # open files a process may have */
#define LINK_MAX 127 /* # links a file may have */
#define MAX_CANON 255 /* size of the canonical input queue */
#define MAX_INPUT 255 /* size of the type-ahead buffer */
#define NAME_MAX 255 /* # chars in a file name */
#define PATH_MAX 4096 /* # chars in a path name including nul */
#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */
#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */
#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */
#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */
#define RTSIG_MAX 32
#endif
轻松入门实战应用从项目开发角度为你搭建完整的知识体系 wangbaoming
[root@localhost ~]#
man 7 pipe
Pipe Capacity
A pipe has a limited capacity. If the pipe is full, then a write(2) will block or fail, depending on
whether the O_NONBLOCK flag is set (see below). Different implementations have different
limits for the pipe capacity. Applications should not rely on a particular capacity: an application
should be designed so that a reading process consumes data as soon as it is available,
so that a writing process does not remain blocked.
In Linux versions before 2.6.11, the capacity of a pipe was the same as the system page size
(e.g., 4096 bytes on x86). Since Linux 2.6.11, the pipe capacity is 65536 bytes.
3 FIFO管道
命名管道
管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
命名管道是一种特殊类型的文件
命名管道和匿名管道区别
管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。
命名管道是一种特殊类型的文件
创建一个命名管道
命名管道可以从命令行上创建,命令行方法是使用下面这个命令:
$ mkfifo filename
命名管道也可以从程序里创建,相关函数有:
int mkfifo(const char *filename,mode_t );
man 3 mkfifo
匿名管道与命名管道PK
匿名管道由pipe函数创建并打开。
命名管道由mkfifo函数创建,打开用open
FIFO(命名管道)与pipe(匿名管道)之间唯一的区别在它们创建与打开的方式不同,一但这些工作完成之后,它们具有相同的语义。
命名管道的打开规则
如果当前打开操作是为读而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
轻松入门实战应用从项目开发角度为你搭建完整的知识体系 wangbaoming
O_NONBLOCK enable:立刻返回成功
如果当前打开操作是为写而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
O_NONBLOCK enable:立刻返回失败,错误码为ENXIO
命名管道的读写规则
同匿名管道
mknod
管道文件不能使用vi打开。。就是vi不能打开看管道内容
4FIFO管道编程实践
利用管道,两个进程间进行文件复制。
fifow
读文件
写入管道
fifor
读管道
写入文件
FIFO(7) Linux Programmer's Manual FIFO(7)
NAME
fifo - first-in first-out special file, named pipe
man 3 mkfifo
mkfifo - make a FIFO special file (a named pipe)
SYNOPSIS
#include
#include
int mkfifo(const char *pathname, mode_t mode);
DESCRIPTION
mkfifo() makes a FIFO special file with name pathname. mode specifies the FIFO's
permissions. It is modi-
fied by the process's umask in the usual way: the permissions of the created file are
(mode & ~umask).
A FIFO special file is similar to a pipe, except that it is created in a different way.
Instead of being an
轻松入门实战应用从项目开发角度为你搭建完整的知识体系 wangbaoming
anonymous communications channel, a FIFO special file is entered into the file system by
calling mkfifo().
Once you 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. Opening a FIFO for reading
normally blocks until some
other process opens the same FIFO for writing, and vice versa. See fifo(7) for
non-blocking handling of FIFO
special files.
RETURN VALUE
On success mkfifo() returns 0. In the case of an error, -1 is returned (in which case,
errno is set appro-
priately).