高级I/O函数(2)-splice函数

splice函数:

功能描述:用于在两个文件描述符之间移动数据,也是零拷贝操作。函数定义如下:

1 #include <fcntl.h>
3   ssize_t splice(int fd_in,loff_t* off_t,int fd_out,loff_t* off_out,size_t len,unsigned int flags);

参数描述:

fd_in:待输入数据的文件描述符.

off_t:如果fd_in是一个管道文件描述符,那么off_t参数必须是NULL,表示从数据流的当前偏移位置读入;如果fd_in不是一个管道文件描述符(例如socket),则它将指出具体的偏移位置.

len:指定移动数据的长度.

flags:则控制数据如何移动,它可以被设置为下表中值的按位异或.

表  splice的flags参数的常用取值及其含义

             常用值 含义
SPLICE_F_MOVE 如果合适的话,按整页内存移动数据.
SPLICE_F_NONBLOCK 非阻塞的splice操作,但实际效果还是会受文件描述符本身的阻塞状态的影响.
SPLICE_F_MORE 给内核一个提示:后续的splice调用将读取更多的数据
SPLICE_F_GIFT 对splice没有效果.

注意:

使用splice函数时,fd_in和fd_out必须至少有一个管道文件描述符.调用成功后返回移动字节的数量.它可能返回0,这发生从管道中读取数据时而该管道没有被写入任何数据.错误返回-1并设置errno.

例子:利用splice函数来实现一个零拷贝的回射服务器模型。

 1 #include <sys/socket.h>
 2 #include <netinet/in.h>
 3 #include <arpa/inet.h>
 4 #include <unistd.h>
 5 #include <stdlib.h>
 6 #include <string.h>
 7 #include <fcntl.h>
 8
 9 int main(int argc,const char* argv[]){
10       if(argc!=2){
11           printf("usage:%s ip_address port_number\n",argv[0]);
12           return -1;
13       }‘
14
15       const char* ip=argv[1];
16       int port=atoi(argv[2]);
17
18       int ret;
19       struct sockaddr_in address;
20       bzero(&address,sizeof(address));
21       address.sin_family=AF_INET;
22       inet_pton(AF_INET,ip,&address.sin_addr);
23       address.sin_port=htons(port);
24
25       int sockfd=socket(AF_INET,SOCK_STREAM,0);
26       assert(sockfd!=-1);
27
28       ret=bind(sockfd,(struct sockaddr*)&address,sizeof(address));
29       assert(ret!=-1);
30
31       ret=listen(sockfd,5);
32       assert(ret!=-1);
33
34       while(1){
35           struct sockaddr_in peer;
36           bzero(&peer,sizeof(peer));
37           socklen_t len=sizeof(peer);
38
39           int connfd=accept(sockfd,(struct sockaddr*)&peer,len);
40           if(connfd<0){
41               printf("errno is:%d\n",errno);
42               break;
43           }
44           else{
45               int pipefd[2];
46               ret=pipe(pipefd);
47               assert(ret!=-1);
48
49               /*将connfd上流入的客户端数据定向到管道中*/
50               ret=splice(connfd,NULL,pipefd[1],NULL,32768,SPLICE_F_MORE|
51                                           SPLICE_F_MOVE);
52               assert(ret!=-1);
53               /*将管道中的数据定向到connfd的客户端文件描述符上*/
54               splice(pipefd[0],NULL,connfd,NULL,32768,SPLICE_F_MORE|
55                                           SPLICE_F_MOVE);
56               assert(ret!=-1);
57            }
58       }
59
60       close(connfd);
61       close(sockfd);
62       return 0;
63 }

我们通过splice函数将从客户端的内容读入到pipefd[1]中,然后再使用splice函数从pipefd[0]中读出该内容到客户端。从而实现了简单高效的回射服务。整个过程为执行recv/send操作,因此未涉及用户空间和内核空间之间的数据拷贝。

时间: 2024-11-05 11:39:10

高级I/O函数(2)-splice函数的相关文章

split()函数,join()函数,splice()函数的学习与总结

前几天做项目,用到这几个函数,在这里进行总结,加深学习理解: 1.split()函数,把一个字符串分割成字符串数组 用法:stringObject.split(separator,howmany): 第一参数,是必须的,是字符串或者正则表达式,表示从该参数指定的地方分割stringObject. 第二个参数,是可选的,该参数返回数组的最大长度. 返回值:一个字符串数组.该数组是通过在 separator 指定的边界处将字符串 stringObject 分割成子串创建的. 注意:想要分割成单个字符

splice()函数的使用方法

splice()函数的使用方法,这是一个拗口的函数.用起来有点麻烦.图3所看到的是splice函数的功能.将一个列表插入到还有一个列表其中.list容器类定义了splice()函数的3个版本号: splice(position,list_value); splice(position,list_value,ptr); splice(position,list_value,first,last); list_value是一个已存在的列表,它将被插入到源列表中,position是一个迭代參数,他当前

JavaScript中splice函数

JavaScript中splice函数方法是从一个数组中移除一个或多个元素,如果必要,在所移除元素的位置上插入新元素,返回所移除的元素. arrayObj.splice( start, deleteCount, [item1[, item2[, . . . [,itemN]]]]) 其中arrayObj必选项.一个 Array 对象. start是必选项.指定从数组中移除元素的开始位置,这个位置是从 0 开始计算的.www.hrbfkyy120.com deleteCount是必选项.要移除的元

linux网络编程九:splice函数,高效的零拷贝

from:http://blog.csdn.net/jasonliuvip/article/details/22600569 linux网络编程九:splice函数,高效的零拷贝 最近在看<Linux高性能服务器编程>,在此做个日记,以激励自己,同时分享于有需要的朋友. 1. splice函数 [cpp] view plain copy #include <fcntl.h> ssize_t splice(int fd_in, loff_t *off_in, int fd_out, 

python局部变量、高级函数、匿名函数、嵌套函数、装饰器

1.局部变量 在函数内部,可以用Global,显式的声明为全局变量.这种方式永远不要这么用. Ctrl+?多行注释i 2.高级函数 把函数名当做参数,传给函数 def add(a,b,f): return f(a)+f(b) res = add(3,-6,abs) abs是内置函数 def bar(): print("in the bar") def test1(func): 首先看第一个例子:def bar(): print("in the bar") def t

用 splice 函数分别实现 push、pop、shift、unshift 的方法

主要需要注意的是不同方法他们本身返回的值应该是什么,是数组当前的长度,还是取出的元素的值,再在splice函数里面进行相应的return就可以了.具体如下: 用 splice函数实现 push方法 function samePush(arr, value){ arr.splice(arr.length, 0, value) return arr.length } var arr = [3, 4, 5] //使用push方法 arr.push(10) // arr 变成[3,4,5,10],返回4

ZOJ 4016 Mergeable Stack(利用list模拟多个栈的合并,STL的应用,splice函数!!!)

Mergeable Stack Time Limit: 2 Seconds      Memory Limit: 65536 KB Given initially empty stacks, there are three types of operations: 1 s v: Push the value onto the top of the -th stack. 2 s: Pop the topmost value out of the -th stack, and print that

JavaScript高级程序设计:第七章 - 函数

六.函数表达式 //把函数当成值来使用的情况下,都可以使用匿名函数 递归 //递归函数是在一个函数通过名字调用自身的情况下构成的 //使用函数声明来定义递归函数可能会出现问题 //这是一个经典的递归阶乘函数 function factorial(num) { if (num<1){ return 1; }else{ return num * factorial(num-1); } } //使用函数声名来定义该递归函数时,函数名和函数体会产生耦合. //当其他指针指向该函数体的时候,由于执行ano

Javascript高级程序设计——第三章:函数

函数Function 通过函数封装多条语句,在任何地方执行.javascript函数不会重载,相同名字函数,名字属于后定义的函数通过function关键词声明. function functionName(arguments){ statement; } 函数会在执行return语句后停止并退出.return语句之后的任何代码不会被执行. function say(){ return “hay”; alert("hay"); //永远不执行 } return后不带返回值的会返回unde