tee函数
tee
函数在两个管道描述符之间复制数据,也是零拷贝操作。它不消耗数据,因此源文件描述符上的数据仍然可以用于后续操作。
1 |
|
fd_in
和fd_out
是文件描述符,但是必须是管道文件描述符
len
参数指定移动数据的长度
flags
参数则控制数据如何移动,它可以被设置为下表中的某些值的按位或,它的参数其实和splice
函数相同。
tee
函数成功时返回在两个文件描述符之间复制的数据数量(字节数)。返回0表示没有复制任何数据。tee
失败时返回-1并设置errno
。
tee
函数在两个管道描述符之间复制数据,也是零拷贝操作。它不消耗数据,因此源文件描述符上的数据仍然可以用于后续操作。
1 | #include <fcntl.h> |
fd_in
和fd_out
是文件描述符,但是必须是管道文件描述符
len
参数指定移动数据的长度
flags
参数则控制数据如何移动,它可以被设置为下表中的某些值的按位或,它的参数其实和splice
函数相同。
tee
函数成功时返回在两个文件描述符之间复制的数据数量(字节数)。返回0表示没有复制任何数据。tee
失败时返回-1并设置errno
。
splice
用于在两个文件描述符之间移动数据,是零拷贝操作。看了man
手册,发现这个splice
函数跟pipe管道关系不浅。
1 | #include <fcntl.h> |
fd_in
参数是待输人数据的文件描述符。如果fd_in
是一个管道文件描述符,那么 off_in
参数必须被设置为NULL。如果fd_in
不是一个管道文件描述符(比如 socket),那么off_in
表示从输入数据流的何处开始读取数据。此时,若off_in
被设置为NULL,则表示从输入数据流的当前偏移位置读入;若off_in
不为NULL,则它将指出具体的偏移位置。
fd_out/off_out
参数的含义与fd_in/off_in
相同,不过用于输出数据流。
len
参数指定移动数据的长度
flags
参数则控制数据如何移动,它可以被设置为下表中的某些值的按位或。
sendfile
函数在两个文件描述符之间直接传递数据(完全在内核中操作),从而避免了内核缓冲区和用户缓冲区之间的数据拷贝,效率很高,这被称为零拷贝。sendfile
函数的定义如下:
1 | #include <sys/sendfile.h> |
out_fd
参数是待写入内容的文件描述符
in_fd
参数是待读取内容的文件描述符
offset
参数是指从读入文件流的哪个位置开始读,如果为空,则使用读入文件流默认的起始位置
count
参数指定在文件描述符in_fd
和out_fd
之间传输的字节数
sendfile
成功时返回传输的字节数,失败则返回-1并设置errno
。
该函数的man手册明确指出,in_fd
必须是一个支持类似mmap
函数的文件描述符,即它必须指向真实的文件,不能是socket和管道。而out_fd
则必须是一个socket。由此可见,sendfile
几乎是专门为在网络上传输文件而设计的。
readv
函数将数据从文件描述符读到分散的内存块中,即分散读;
writev
函数则将多块分散的内存数据一并写人文件描述符中,即集中写。它们的定义如下:
1 | #include <sys/uio.h> |
fd
被操作的目标文件描述符。
iov
是iovec
类型的数组,在recvmsg
和sendmsg
中接触过。
iovcnt
是iov
数组的长度。
dup
和dup2
用于复制文件描述符,通常用于重定向。
1 | #include <unistd.h> |
dup
函数创建一个新的文件描述符,该新文件描述符和原有文件描述符oldfd
指向相同的文件、管道或者网络连接。并且dup返回的文件描述符总是取系统当前可用的最小整数值。
dup2
和dup
类似,不过它将返回第一个不小于newfd
的整数值的文件描述符,并且newfd
这个文件描述符也将会指向oldfd
指向的文件,原来的newfd
指向的文件将会被关闭(除非newfd
和oldfd
相同)。
dup
和dup2
系统调用失败时返回-1并设置errno
,成功就返回新的文件描述符。
注意:通过dup和dup2创建的文件描述符并不继承原文件描述符的属性,比如close-on-exec和non-blocking 等
学习《Linux高性能服务器编程》第五章Linux网络编程基础API,为了印象深刻一些,多动手多实践,所以记下这个笔记。这一篇主要记录Linux中socket网络信息查询API,包括gethostbyname和gethostbyaddr、getservbyname和getservbyport、getaddrinfo、getnameinfo。
socket当中两要素:IP和端口号,都是用数值表示的。但是有时候我们可以使用主机名代替IP,使用服务名代替端口号。
1 | telnet 127.0.0.1 80 |
这个功能就是使用网络信息API实现的。
读取和设置socket文件描述的方法如下
1 | #include <sys/types.h> /* See NOTES */ |
sockfd
参数指定被操纵的目标socket,level
参数指定要操作的协议选项,optname
参数则指定选项的名字,optval
和optlen
参数分别是操作选项的值和长度。截图了一下书中的表格。