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时,系统自动配置;
length:内存的长度。
prot: 用来设置内存段的访问权限;PROT_READ:内存可读;PROT_WRITE :内存可写;PROT_EXEC 内存段可执行;PROT_NONE: 内存段不能被访问。
flags:控制内存段内容被修改后的行为;MAP_SHARED:进程间共享这段内存,对该内存的修改将反映到被映射的文件中。MAP_PRIVATE:内存段位调用进程所私有,对该内存段的修改不会映射到文件中;MAP_ANONYMOUS:这段内存不是从映射过来的。其内容被初始化为0,可以省略后两个参数。
MAP_FIXED:内存段必须位于start参数指定的地址处,start是内存页面大小(4096)的整数倍.
MAP_HUGETLB:按照大内存页面分配内存空间。
splice函数
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);
fd_in:是待输入数据的文件描述符;若fd_in 是管道文件符,则off_in是NULL;如果fd_in不是管道文件符,则off_in表示从何处开始读取数据,若off_in被设置为NULL,表示输入数据流的当前偏移位置读入。
fd_out和off_out是用于输出数据流;
len:指定移动数据的长度;
flags:指控制如何移动数据
splice的flags常用值:
SPLICE_F_MOVE:若可以,则整页移动;
SPLICE_F_NONBLOCK:非阻塞的操作
SPLICE_F_MORE:给内核提示:后续调用splice读取更多的数据
使用splice函数实现的回射服务器:
#include<sys/sock.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<cstdio>
#include<cstdlib>
#include<unistd>
#include<cstring>
#include<fcntl.h>
#include<iostream>
using namespace std;
int main(int argc,char* argv[])
{
if (argc < 2)
{
cout<<"usage :"<<basename(argv[0])<<"ip_address port_number"<<endl;
return 1;
}
const char * ip = argv[1];
int port = atoi(argv[2]);
struct sockaddr_in address;
bzero(&address,sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET,ip,&address.sin_addr);
address.sin_port = htons(port);
int sock = socket(PF_INET,SOCK_STREAM,0);
assert(sock >= 0);
int ret = bind(sock,(struct sockaddr*) &address,sizeof(address));
assert(ret != -1);
struct sockaddr_in client;
socklen_t client_addrlength = sizeof(client);
int connfd = accept(sock,(struct sockaddr*)&client,&client_addrlength);
if(connfd < 0);
{
cout<<"errno is"<<errno;
}
else
{
int piped[2];
assert(ret != -1);
ret = pipe(piped);
ret = splice(connfd, NULL,piped[1],NULL,321786,SPLICE_F_MORE|SPLICE_F_MOVE);
assert(ret != -1);
ret = splice(piped[0],NULL,connfd,NULL,321786,SPLICE_F_MORE|SPLICE_F_MOVE);
assert(ret != -1);
close(connfd);
}
close(sock);
return 0 ;
}