6 高级IO函数
6.1 pipe函数
pipe函数创建一个管道,用于实现进程间通信
#include<unistd.h>
int pipe(int fd[]);
参数包含两个文件描述符fd[0]和fd[1],往fd[1]写入的数据可以从fd[0]读出
默认情况下这对文件描述符都是阻塞的。如果用read调用读取一个空管道,read将会阻塞直到有数据可读为止;write类似。
如果将fd[0]\fd[1]都设置为非阻塞,则read和write会有不同行为。如果fd[1]引用计数减少到0,即没有任何进程需要往管道写入数据,则对fd[0]的read操作返回0,即读到了EOF;反之,如果fd[0]引用计数减少至0,则对fd[1]的write操作将失败,并引发SIGPIPE信号。
管道内部传输的数据是字节流,这和TCP字节流的概念相同。从Linux 2.6.11开始,管道容量的大小是默认65536字节。可以使用fcntl修改。
socketpair函数可以方便的创建双向管道:
#include<sys/types.h>
#include<sys/socket.h>
int socketpair(int domain, int type, int protocol, int fd[]);
6.2 dup函数和dup2函数
复制文件描述符,它们经常用来重定向进程的stdin、stdout和stderr。文件描述符是与打开文件或者数据流 相关联的整数, 0、1、2 是系统保留的三个文件描述符,分别对应标准输入、标准输出、标准错误
#include<unistd.h>
int dup(int file_descriptor);
int dup2(int file_descriptor_one, int file_descriptor_two);
利用函数dup,我们可以复制一个描述符。传给该函数一个既有的描述符,它就会返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝。这意味着,这两个描述符共享同一个数据结构。
dup2函数跟dup函数相似,但dup2函数允许调用者规定一个有效描述符和目标描述符的id。dup2函数成功返回时,目标描述符(dup2函数的第二个参数)将变成源描述符(dup2函数的第一个参数)的复制品,换句话说,两个文件描述符现在都指向同一个文件,并且是函数第一个参数指向的文件。
通过dup和dup2创建的文件描述符并不继承原来的文件描述符的属性,比如close-on-exec和non-blocking等。
例子:CGI服务器的基本原理
int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
if ( connfd < )
{
printf( "errno is: %d\n", errno );
}
else
{
close( STDOUT_FILENO );
dup( connfd );
printf( "abcd\n" );
close( connfd );
}
关闭标准输出文件描述符,dup总返回系统最小的可用文件描述符,所以实际返回值是1,这样就将所连接的socket文件描述符connfd定位到标书输出,printf调用的输出将被客户端获得,这就是CGI服务器的基本原理
6.3 readv函数和writev函数
读指从文件描述符读到内存,写指从内存写入文件描述符
readv函数将数据从文件描述符读到分散的内存块中,即分散读;writev函数则将多块分散的内存数据一并写入文件描述符中,即集中写。
#include<sysy/uio.h>
ssize_t readv(int fd, const struct iovec* vector, int count);
ssize_t writev(int fd, const struct iovec* vector, int count);
struct iovec {
void *iov_base; //starting address
size_t iov_len; //number of bytes to transfer
};
例子:web服务器对客户端的HTTP请求响应,HTTP应答包含1个状态行,多个头部字段,1个空行和文档内容,这些可能不在一起,可以用writev写入一个文件描述符
struct iovec iv[];
iv[ ].iov_base = header_buf;
iv[ ].iov_len = strlen( header_buf );
iv[ ].iov_base = file_buf;
iv[ ].iov_len = file_stat.st_size;
ret = writev( connfd, iv, );
6.4 sendfile函数
sendfile在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了内核缓冲区和用户缓冲区之间的数据拷贝,效率很高,这被称为零拷贝。
#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count);
in_fd必须是一个支持类似mmap函数的文件描述符,即它必须指向真实的文件,不能是socket和管道;
而out_fd则必须是一个socket,由此可见,sendfile几乎是专门为在网络上传输文件设计的。
offset:读入位置
count:传输字节数
6.5 mmap函数和munmap函数
mmap函数用于申请一段内存空间。我们可以将这段内存作为进程间通信的共享内存,也可以将文件直接映射到其中。munmap释放这段内存空间。
#include <sys/mman.h>
void* mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *start, size_t length);
start可以指定这段内存的起始地址,当为NULL时,系统自动分配一个地址。
prot参数用来设置访问权限。按位或:
PROT_READ //内存可读
PROT_WRITE //内存可写
PROT_EXEC //内存段可执行
PROT_NONE //内存段不能被访问
flags参数控制内存段修改后的行为
6.6 splice函数
用于在两个文件描述符之间移动数据,也是零拷贝操作
#include <fcntl.h>
ssize_t splice(int fd_in, loff_t* off_in, int fd_out, loff_t* off_out, size_t len, unsigned int flags);
使用splice函数,fd_in和fd_out必须至少有一个是管道文件描述符,splice函数调用成功时返回移动字节的数量
如果fd_in是管道描述符,那么off_in必须为NULL。若不是管道,则标示从什么位置读取,fd_out类似
flags参数:
SPLICE_F_MOVE //按整页内存移动数据,只是给内核一个提示,没有实际效果。
SPLICE_F_NONBLOCK //实际效果还会受到文件描述符本身的阻塞状态影响。
SPLICE_F_MORE //给内核一个提示:后续的splice调用将读取更多数据。
SPLICE_F_GIFT //没有效果
例子:使用splice函数实现的echo服务器
int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
if ( connfd < )
{
printf( "errno is: %d\n", errno );
}
else
{
int pipefd[];
assert( ret != - );
ret = pipe( pipefd );
ret = splice( connfd, NULL, pipefd[], NULL, , SPLICE_F_MORE | SPLICE_F_MOVE ); //从connfd流入的客户端数据定向到管道
assert( ret != - );
ret = splice( pipefd[], NULL, connfd, NULL, , SPLICE_F_MORE | SPLICE_F_MOVE ); //将管道输出定向到connfd客户端连接的文件描述符
assert( ret != - );
close( connfd );
}
6.7 tee函数
在两个管道文件描述符之间复制数据,也是零拷贝。它不消耗数据,因此源文件描述符上的数据仍然可以用于后续的读操作
#include <fcntl.h>
ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags);
6.8 fcntl函数
提供了对文件描述符的各种控制操作
#include <fcntl.h>
int fcntl(int fd, int cmd, ...);
在网络编程中,fcntl函数通常用来将一个文件描述符设置为非阻塞的 重要常用
#include <fcntl.h>
int fcntl(int fd, int cmd, ...);
int setnonblocking(int fd)
{
int old_option = fcntl( fd ,F_GETFD ); //获取文件描述符旧状态标志
int new_option = odl_option | O_NONBLOCK; //设置非阻塞标志
funcl( fd, F_SETFL, new_option);
return old_option; //返回旧状态以便日后恢复
}
6 高级IO函数的更多相关文章
- 第14章——高级IO函数
1.套接字超时 套接字IO函数设置超时的方法有三种: (1)调用alarm. (2)select (3)使用SO_RECTIMEO和 SO_SNDTIMEO 选项 上面三种方法适用于输入输出操作(re ...
- UNIX高级环境编程(7)标准IO函数库 - 二进制文件IO,流定位,创建临时文件和内存流
1 二进制IO(Binary IO) 在前一篇我们了解了逐字符读写和逐行读写函数. 如果我们在读写二进制文件,希望以此读写整个文件内容,这两个函数虽然可以实现,但是明显会很麻烦且多次循环明显效率很低. ...
- UNIX高级环境编程(6)标准IO函数库 - 流的概念和操作
标准IO函数库隐藏了buffer大小和分配的细节,使得我们可以不用关心预分配的内存大小是否正确的问题. 虽然这使得这个函数库很容易用,但是如果我们对函数的原理不熟悉的话,也容易遇到很多问题. 1 ...
- (十一) 一起学 Unix 环境高级编程 (APUE) 之 高级 IO
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- 标准C IO函数和 内核IO函数 效率(时间)比较
前言 标准C提供的文件相关的IO函数,除标准错误输出是不带缓冲的(可以尽快的将错误消息显示出来)之外,所有与终端相关的都是行缓冲,其余都是全缓冲的. 我们可以使用setbuf,setvbuf改变指定流 ...
- 高级IO
# 高级IO 特殊的IO操作,包括文件锁.系统V的流.信号驱动的I/O.多路转I/O(select和pull函数).readv和writev函数以及存贮映射I/O等概念和函数. ## 文件锁 文件锁是 ...
- linux网络编程之IO函数
Linux操作系统中的IO函数主要有read(),write(),recv(),send(),recvmsg(),sendmsg(),readv(),writev(). 接收数据的recv()函数 # ...
- linux_api之高级IO
本篇索引: 1.引言 2.非阻塞IO 3.记录锁(文件锁) 4.io多路复用(I/O multiplexing ) 5.异步IO 6.存储映射IO 1.引言 我们第三篇学习了对IO的open.read ...
- python高级之函数
python高级之函数 本节内容 函数的介绍 函数的创建 函数参数及返回值 LEGB作用域 特殊函数 函数式编程 1.函数的介绍 为什么要有函数?因为在平时写代码时,如果没有函数的话,那么将会出现很多 ...
随机推荐
- svn的使用!!!
1.SVN:subversion(子级源代码版本控制管理软件) 2.SVN的作用 (1)避免开发同一项目不会出现代码覆盖. (2)同一文件可以创建许多不同的版本,并可以随时查看不同版本的内容. (3) ...
- C#导出GridView数据到Excel文件类
using System; using System.Web; using System.Web.UI; using System.IO; using System.Web.UI.WebControl ...
- SQL Server 基础:Cast和Convert的区别
CAST 和 CONVERT 都可以将某种数据类型的表达式显式转换为另一种数据类型. 语法: CAST ( expression AS data_type ) CONVERT (data_type[( ...
- ASP.NET中前台调用后台的方法
学习文章:http://www.cnblogs.com/kingteach/archive/2010/11/12/1875633.html 练习代码: 前台: <html xmlns=" ...
- IOS笔记 : addChildViewController
一下addChildViewController,一个ViewController可以添加多个子ViewController,但是这 些子ViewController只有一个是显示到父视图中的,可以通 ...
- tomcat生成ssl证书
转载:http://www.cnblogs.com/sixiweb/p/3339698.html 1.1 生成keystore文件及导出证书 打开控制台: 运行: %JAVA_HOME%\bin\ke ...
- hdu 1622 Trees on the level
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1622 小白书上的题... #include<algorithm> #include< ...
- TFS使用指南
上一篇文章已经简略介绍过TFS的安装与管理,本篇文章主要描述一下我个人在工作过程中使用TFS的一些指南与建议.本章内容预览: 1. 项目计划与跟踪 经常有很多朋友在日常聊天中抱怨做计划很无畏,因为计 ...
- iOS另类的内存管理
iOS的内存管理算是老生常谈的问题了,我们写iOS的时候无时无刻不在涉及到内存管理.从开始的MRR(manual retain-release)到后来ARC(Automatic Reference C ...
- FPGA入门1
FPGA入门知识介绍 近几年来,由于现场可编程门阵列(FPGA)的使用非常灵活,又可以无限次的编程,已受到越来越多的电子编程者的喜爱,很多朋友都想学习一些FPGA入门知识准备进行这个行业,现在关 ...