第4章 管道和FIFO
4.1 管道
管道是由pipe函数创建的,提供一个单向数据流。
| 头文件 | #include <unistd.h> |
| 函数原型 | int pipe(int fd[2]); |
| 返回值 | 成功则为0,出错则为-1 |
| 函数功能 | 该函数返回两个文件描述符:fd[0]和fd[1]。fd[0]用来读操作,fd[1]用来写操作 |
| 说明 | 管道只能用于有亲缘关系进程间通讯。要实现非亲缘关系进程间通讯用有名管道FIFO |
4.2 管道实现半双工通讯
实现的步骤:
(1)创建管道(fd[0]和fd[1])
(2)fork
(3)父进程关闭管道的读端(fd[0])
(4)子进程关闭管道的写端(fd[1])
(5)父进程往管道的写端(fd[1])写入数据
(6)子进程从管道的读端(fd[0])读出数据
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_MAX_LEN 10
int main()
{
pid_t childpid = ;
] = {};
] = {};
// 创建管道
)
{
printf("pipe error");
;
}
// 创建进程
childpid = fork();
)
{
printf("fork error\n");
;
}
// 子进程
)
{
close(pipefd[]);
read(pipefd[], buf, BUF_MAX_LEN);
printf("child:%s\n", buf);
exit();
}
// 父进程
close(pipefd[]);
write(pipefd[], "hello", sizeof("hello"));
printf("parent:%s\n", "hello");
waitpid(childpid, NULL, );
;
}
4.3 管道实现全双工通讯
实现的步骤:
(1)创建管道1(fd1[0]和fd1[1])、管道2(fd2[0]和fd2[1])
(2)fork
(3)父进程关闭管道1的读端(fd1[0])、关闭管道2的写端(fd2[1])
(4)子进程关闭管道1的写端(fd1[1])、关闭管道2的读端(fd2[0])
(5)父、子进程间通讯
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_MAX_LEN 10
int main()
{
pid_t childpid = ;
] = {};
] = {};
] = {};
// 创建管道fd1
)
{
printf("pipe error");
;
}
// 创建管道fd2
)
{
printf("pipe error");
;
}
// 创建进程
childpid = fork();
)
{
printf("fork error\n");
;
}
// 子进程
)
{
sleep();
close(pipefd1[]);
close(pipefd2[]);
read(pipefd1[], buf, BUF_MAX_LEN);
printf("child read:%s\n", buf);
write(pipefd2[], "hi", sizeof("hi"));
exit();
}
// 父进程
close(pipefd1[]);
close(pipefd2[]);
write(pipefd1[], "hello", sizeof("hello"));
read(pipefd2[], buf, BUF_MAX_LEN);
printf("parent read:%s\n", buf);
waitpid(childpid, NULL, );
;
}
4.4 popen 和 pclose 函数
| 头文件 | #include <stdio.h> | |
| 函数原型 | FILE *popen(const char *command, const char *type); | |
| int pclose(FILE *stream); | ||
| 返回值 | 成功返回文件描述符,失败返回NULL | |
| 参数 | command | shell命令,这行命令将被传到 bin/sh 并使用-c 标志 |
| type | r:读到commond的标准输出 | |
| w:写到command的标准输入 | ||
| 说明 | popen创建的文件描述符,必须由pclose关闭。 | |
#include <stdio.h>
#include <string.h>
#define BUF_MAX_LEN 100
int main()
{
FILE *fp = NULL;
] = {};
fp = popen("ls", "r");
if (fp == NULL)
{
printf("popen error\n");
;
}
while (fgets(buf, BUF_MAX_LEN, fp) != NULL)
{
fputs(buf, stdout);
}
pclose(fp);
;
}
4.5 FIFO
FIFO由mkfifo函数创建。
| 头文件 |
#include <sys/types.h> #include <sys/stat.h> |
|
| 函数原型 | int mkfifo(const char *pathname, mode_t mode); | |
| 返回值 | 成功返回0,出错返回-1 | |
| 参数 | pathname | 一个普通的路径名,它是该FIFO名字 |
| mode | 文件的权限 | |
| 说明 | 1.mkfifo函数已隐含O_CREAT | O_EXCL,只能创建一个新的FIFO | |
| 2.如要打开存在的FIFO,首先调用mkfifo,然后判断返回值是否为EEXIST,若返回该错误,再调用open或fopen | ||
| 3.FIFO只能读或者写,不能即读又写的,因为它是半双工的 | ||
| 4.对FIFO写总是追加到末尾,对FIFO读总是从头开始,对FIFO调用lseek,则返回ESPIPE错误 | ||
| 5.open打开FIFO文件时,如果以只写方式没有打开,则只读方式的open会一直阻塞 | ||
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#define FIFO1 "/tmp/fifo1"
#define FIFO2 "/tmp/fifo2"
#define BUF_MAX_LEN 10
int main()
{
;
;
pid_t childpid = ;
] = {};
// 打开2个FIFO
) < ) && (errno != EEXIST))
{
printf("mkfifo error:cannot open %s\n", FIFO1);
;
}
) < ) && (errno != EEXIST))
{
unlink(FIFO1);
printf("mkfifo error:cannot open %s\n", FIFO2);
;
}
// fork子进程
childpid = fork();
)
{
unlink(FIFO1);
unlink(FIFO2);
printf("fork error\n");
;
}
// child
)
{
readfd = open(FIFO1, O_RDONLY, );
writefd = open(FIFO2, O_WRONLY, );
write(writefd, "hi", sizeof("hi"));
read(readfd, buf, BUF_MAX_LEN);
printf("child recv:%s\n", buf);
close(readfd);
close(writefd);
exit();
}
// parent
writefd = open(FIFO1, O_WRONLY, );
readfd = open(FIFO2, O_RDONLY, );
write(writefd, "hello", sizeof("hello"));
read(readfd, buf, BUF_MAX_LEN);
printf("parent recv:%s\n", buf);
waitpid(childpid, NULL, );
close(readfd);
close(writefd);
unlink(FIFO1);
unlink(FIFO2);
;
}
4.6 管道和FIFO的区别
(1)创建并打开一个管道只需调用pipe。创建并打开一个FIFO则需要在调用mkfifo后再调用open。
(2)管道在所有进程都关闭后自动关闭。FIFO的名字则只能通过调用unlink才从文件系统中删除。
(3)FIFO有一个名字,可以供无亲缘关系的进程间通讯,管道不可以。
4.7 管道和FIFO的额外属性
(1)将描述符设置成非阻塞。
(2)write写入的字节数小于或等于PIPE_BUF(Posix限制),那么write操作是原子性的;如果写入数据大于PIPE_BUF,那么write操作不保证原子性。O_NOBLOCK标志对write的原子性没有影响
(3)如果向一个没有读打开的管道或FIFO写入,那么内核将产生一个SIGPIPE信号。
第4章 管道和FIFO的更多相关文章
- 第4章 管道与FIFO
4.1 概述 管道只在亲缘进程间使用,FIFO在任意进程间使用 4.2 管道 #include <unistd.h> ]) fd[0]用来读管道,fd[1]用来写管道 1)命令who | ...
- 第四章:管道与FIFO
4.1:概述 管道是最初的Unix IPC形式,可追溯到1973年的Unix第三版.尽管对于许多操作来说很有用,但它们的根本局限在于没有名字,从而只能由亲缘关系的进程使用.这一点随FIFO的加入得改正 ...
- 管道和FIFO 一
管道和FIFO 管道(pipe) 管道在Unix及Linux进程间通信是最基础的,很容易理解.管道就像一个自来水管,一端注入水,一端放出水,水只能在一个方向上流动,而不能双向流动.管道 ...
- linux进程间通信-有名管道(FIFO)
有名管道(FIFO) 命名管道也被称为FIFO文件,是一种特殊的文件.由于linux所有的事物都可以被视为文件,所以对命名管道的使用也就变得与文件操作非常统一. (1)创建命名管道 用如下两个函数中的 ...
- Linux系统编程——进程间通信:命名管道(FIFO)
命名管道的概述 无名管道,因为没有名字,仅仅能用于亲缘关系的进程间通信(很多其它详情.请看<无名管道>).为了克服这个缺点.提出了命名管道(FIFO).也叫有名管道.FIFO 文件. 命名 ...
- [转] IPC之管道、FIFO、socketpair
管道和FIFO作为最初的UNIX IPC形式,现在已用得较少.SocketPair可作为全双工版本的管道,较为常用,这里简单做个笔记 管道 * 只用于有亲缘关系的进程间通信 * 单向,即半双工 (双向 ...
- linux 有名管道(FIFO)
http://blog.csdn.net/firefoxbug/article/details/8137762 linux 有名管道(FIFO) 管道的缓冲区是有限的(管道制存在于内存中,在管道创建时 ...
- UNIX环境高级编程——管道和FIFO限制
系统加于管道和FIFO的唯一限制为: OPEN_MAX 一个进程在任意时刻打开的最大描述符数: PIPE_BUF 可原子的写往一个管道或FIFO的最大数据量. OPEN_MAX的值 ...
- UNIX环境高级编程——管道和FIFO的额外属性
一个描述符能以两种方式设置成非阻塞. (1)调用open时可以指定O_NONBLOCK标志. writefd = open(FIFO1,O_WRONLY | O_NONBLOCK,0); (2)如果一 ...
随机推荐
- $.ajax提交,后台接受到的值总是乱码?明天再总结
//首先说明,我的服务器和页面编码都是GBK,所以尝试了很多种GBK的方式前台:function printFunction(){ window.print(); $.ajax({ url : '/t ...
- ctf之加密
from:http://drops.wooyun.org/tips/10002 0x01 Base64 Base64:ZXZhbCgkX1BPU1RbcDRuOV96MV96aDNuOV9qMXVfU ...
- SqlServer数据文件增长也很快,到底是哪些表增长造成的呢?
查询数据库中所有表的大小,哪些表的数据量较大 create table #t (name ), rows ), data ), index_size ), unused )) exec sp_MSfo ...
- hadoop(四):配置参数
hadoop参数配置,主要是配置 core-site.xml,hdfs-site.xml,mapred-site.xml 三个配置文件,core-site.xml是全局配置,hdfs-site.xml ...
- [转]Python中urllib与urllib2的区别与联系
引用文章1:http://my.oschina.net/u/558071/blog/144792 引用文章2:http://zhuoqiang.me/python-urllib2-usage.html ...
- [原]对Linux环境下任务调度一点认识
我一直以来有一个误解,那就是在终端运行某个程序时,按下Ctrl + D时我误以为就是杀死了这个进程,今天才知道原来不是.比如我利用libevent在Linux环境下写了一个网络监听程序,当启动程序之后 ...
- css之伪类选择器:before :after(::before ::after)
一.总结: ::before是在标签内容前面添加内容, ::after是在标签内容后面添加内容 ::before ::after与:before :after的区别:css3中修订后的伪元素使用:: ...
- 剑指offer系列17---顺时针打印矩阵(不是很懂)
package com.exe4.offer; import java.util.ArrayList; /** * 17[题目]输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果 ...
- 目前已经知道的乐视所有产品各个型号的强刷方法!更新X50
http://ui.letv.com/thread-43668-1-1.html 很多网友买来电视/盒子仅仅要看,还要折腾这个电视,有时候不小心把系统折腾死了,肿么办?危难之中显身手,我的神帖来了,敬 ...
- [cmd]linux 常用命令
1. 磁盘/文件大小中占用情况 df -h: 磁盘大小占用情况 du -h file: 文件夹大小,du -ah file文件夹内所有文件占用情况 du -sh dir: 可以查看文件夹大小,而不列出 ...