linux中管道(pipe)一谈

时间:2022-09-26 00:04:53
/***********************************************
管道(pipe)是Linux上进程间通信的一种方式,其是半双工(数据流只能在一个方向上流动(还需要经过内核),及要么是接收,要么是发送),并且只能在父子进程 或 具有公共祖先的两个子进程间通信。
管道(pipe)一般是在调用fork函数之前调用pipe函数创建,这样的话,fork后子进程将得到父进程的两个管道描述符副本(相当于调用了两次dup)。 /***********************************************
相关函数:
#include <unistd.h>
int pipe(int fd[2])
返回值:成功返回0,失败返回-1
***********************************************/
注意: 函数执行成功后为参数返回两个描述符,fd[0]为读而打 开,fd[1]为写而打开 很多系统在stat结构体st_size成员中储存管道中可用于读写字节数。但这是不可移植的。(对于struct stat不了解的请百度) 使用管道有几点注意事项:
1.当读(read)一个写(write)端已经关闭的管道,程序(read)将读完管道中所有数据后返回0。
2.当写(write)一个读(write)端已经关闭的管道,将产SIGPIP信号,程序(write)返回-1,并将错误码置为EPIPE
3.如果管道中数据为空,则(read)将永久堵塞直到有数据或写(write)端关闭。
4.如果管道已被数据填满,则(write)将会堵塞直到管道中有空与空间 或 写端(read)关闭,(管道容量可用fpathconf函数得到,使用_PC_PIPE_BUF参数)。
***********************************************/
实例1:
使用管道实现 ls -l | wc -c 操作 分析:
执行ls -l后其结果将会被打印到终端(即使用到STDOUT_FILENO)标准输出,wc -c(统计单词数量)是从标准输入中得到内容(即使用到STDIN_FILENO)然后进行统计。 思路:
子进程中调用exec函数族执行ls -l命令,并调用dup2函数将子进程中的fd[1]描述符复制为标准输出(STDOUT_FILENO),这用的话,但向标准输出中写数据是就等同于向管道中写数据。
对于父进程则调用exec函数族执行wc -c命令,然后调用dup2将fd[0]复制为标准输入, 实例代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h> int main(int argc, char **argv)
{
pid_t pid;
int fd[2]; /**创建管道**/
if (pipe(fd) < 0) {
perror("pipe error");
return EXIT_FAILURE;
} /**调用fork函数创建子进程**/
if ((pid = fork()) < 0) {
perror("fork error");
return EXIT_FAILURE;
} else if (0 == pid) {
close(fd[0]); /**关闭不必要的描述符**/
if (fd[1] != STDOUT_FILENO) {
if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2 error to stdout");
return EXIT_FAILURE;
}
close(fd[1]);
} execlp("ls", "ls", "-l", NULL);
exit(EXIT_SUCCESS);
} //sleep(2);
close(fd[1]);
if (fd[0] != STDIN_FILENO) {
if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) {
perror("dup2 error to stdin");
return EXIT_FAILURE;
}
close(fd[0]);
} execlp("wc", "wc", "-c", NULL); /**回收子进程的退出状态,避免产生僵死进程**/
if (waitpid(pid, NULL, 0) < 0) {
perror("waitpid error");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
实例2:
实现分页功能 即more命令 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h> #define PAGE "/bin/more"
#define MAXLINE 1024 int main(int argc, char **argv)
{
pid_t pid;
int fd[2];
char line[MAXLINE];
char *page = NULL, *temp = NULL, *arg = NULL;
FILE *fp = NULL; if (argc != 2) {
printf("Usage: %s <filename>\n", argv[0]);
return EXIT_FAILURE;
} if ((fp = fopen(argv[1], "r")) == NULL) {
perror("fopen error");
return EXIT_FAILURE;
} if (pipe(fd) < 0) {
perror("pipe error");
return EXIT_FAILURE;
} if ((pid = fork()) < 0) {
perror("fork error");
return EXIT_FAILURE;
} else if (0 == pid) {
close(fd[0]); int len;
while (fgets(line, MAXLINE, fp) != NULL) {
len = strlen(line); int offset = 0, n = 0;
while (len) {
n = write(fd[1], line+offset, len);
offset += n;
len -= n;
}
} if (ferror(fp)) {
perror("fgets errro");
return EXIT_FAILURE;
} fclose(fp);
close(fd[1]);
} close(fd[1]); if (fd[0] != STDIN_FILENO) {
if (dup2(fd[0], STDIN_FILENO) != STDIN_FILENO) {
perror("dup2 error to stdin");
return EXIT_FAILURE;
} close(fd[0]);
} /***得到PAGE对应的环境参数***/
if ((page = getenv("PAGE")) != NULL) {
arg = page;
} else {
arg = PAGE;
} /**
*strrchr函数判断'\'字符,
*在arg字符串中最后一次出现的位置
**/
if ((temp = strrchr(arg, '/')) != NULL) {
temp++;
} else {
temp = arg;
} execl(arg, temp, NULL); if (waitpid(pid, NULL, 0) < 0) {
perror("waitpid error");
return EXIT_FAILURE;
} return EXIT_SUCCESS;
}

linux中管道(pipe)一谈的更多相关文章

  1. Linux中的pipe&lpar;管道&rpar;与named pipe&lpar;FIFO 命名管道&rpar;

    catalogue . pipe匿名管道 . named pipe(FIFO)有名管道 1. pipe匿名管道 管道是Linux中很重要的一种通信方式,是把一个程序的输出直接连接到另一个程序的输入,常 ...

  2. Linux进程间通信 -- 管道&lpar;pipe&rpar;

    前言    进程是一个独立的资源管理单元,不同进程间的资源是独立的,不能在一个进程中访问另一个进程的用户空间和内存空间.但是,进程不是孤立的,不同进程之间需要信息的交互和状态的传递,因此需要进程间数据 ...

  3. Linux进程间通信—管道

    Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...

  4. Linux进程间通信之管道&lpar;pipe&rpar;、命名管道&lpar;FIFO&rpar;与信号&lpar;Signal&rpar;

    整理自网络 Unix IPC包括:管道(pipe).命名管道(FIFO)与信号(Signal) 管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道 ...

  5. Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

    Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博 ...

  6. Linux 进程间通信之管道&lpar;pipe&rpar;&comma;&lpar;fifo&rpar;

     无名管道(pipe) 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信: 定义函数: int pipe(int f ...

  7. Linux学习笔记——管道PIPE

    管道:当从一个进程连接数据流到另一个进程时,使用术语管道(pipe).# include <unistd.h> int pipe(int filedes[2]); //创建管道 pipe( ...

  8. 【Linux 应用编程】进程管理 - 进程间通信IPC之管道 pipe 和 FIFO

    IPC(InterProcess Communication,进程间通信)是进程中的重要概念.Linux 进程之间常用的通信方式有: 文件:简单,低效,需要代码控制同步 管道:使用简单,默认阻塞 匿名 ...

  9. 浅谈Linux中的信号处理机制(二)

    首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...

随机推荐

  1. &lbrack;转&rsqb;oracle for update和for update nowait的区别

    1概念小结:(针对以下引用区域内容) 1.1 普通select语句不加锁. 1.2 for update和for update nowait都试图将符合条件的数据加上行级锁.用于排斥其他针对这个表的写 ...

  2. openfire:Openfire源代码在eclipse中的运行配置 &plus; 与spark结合进行二次开发

    1.下载源代码:http://www.igniterealtime.org/downloads/source.jsp 2.把源代码解压出的openfire_src文件夹放至eclipse workpl ...

  3. tomcat设置端口号&comma;访问指定ip就访问指定项目

    1.修改背景: A.通常我们访问我们的web应用格式为: http://ip:端口号/项目名称 例如: http://127.0.0.1:8080/projectName B.如果想直接输入&quot ...

  4. webpack 4 简单介绍

    webpack是什么? webpack是一个现代JavaScript应用程序的静态模块打包器(module bundler). 为什么要使用webpack呢? 随着web技术的发展,前端开发不再仅仅是 ...

  5. sklearn&period;linear&lowbar;model&period;LogisticRegression参数说明

    目录 sklearn.linear_model.LogisticRegression sklearn.linear_model.LogisticRegressionCV sklearn.linear_ ...

  6. php7 三元运算 精简

    $abc = isset($_GET['name'])?$_GET['name']:'abc'; // 5.+ $abcd = $_GET[

  7. &lbrack;Big Data - Kafka&rsqb; Kafka设计解析(五):Kafka Benchmark

    性能测试及集群监控工具 Kafka提供了非常多有用的工具,如Kafka设计解析(三)- Kafka High Availability (下)中提到的运维类工具——Partition Reassign ...

  8. HDU 1427 速算24点 (深搜)

    题目链接 Problem Description 速算24点相信绝大多数人都玩过.就是随机给你四张牌,包括A(1),2,3,4,5,6,7,8,9,10,J(11),Q(12),K(13).要求只用' ...

  9. STS 设置 注解提示

    1.window -> Preferences

  10. JavaWeb温习之防止表单重复提交

    表单重复提交主要有以下三种情况: 1. 在网络延迟的情况下让用户有时间点击多次submit按钮导致表单重复提交 2. 表单提交后用户点击[刷新]按钮导致表单重复提交 3. 用户提交表单后,点击浏览器的 ...