导航:[首页]->[cpp]->[linux 零拷贝技术]

使用mmap代替read/write

以下代码读取某文本中的内容

#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>


int main(int argc, char** argv) 
{
    int fd = open("/tmp/fuck",O_RDONLY);
    if(fd < 0)
    {
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1;
    }

    struct stat sb;
    if (fstat(fd, &sb) == -1)
    {
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1;
    }
    const char* buf = (const char*)mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
    if (buf == MAP_FAILED)
    {
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1;
    }
    printf("%s\n",buf);
    close(fd);
    return 0;
}

sendfile

以下代码拷贝一个文件

#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sendfile.h>


int main(int argc, char** argv) 
{
    int fd = open("/tmp/fuck",O_RDONLY | O_RDONLY);
    if(fd < 0)
    {
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1;
    }
    int fd2 = open("/tmp/fuck1",O_CREAT | O_TRUNC | O_WRONLY);
    if(fd2 < 0)
    {
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1;
    }

    struct stat sb;
    if (fstat(fd, &sb) == -1)
    {
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1;
    }
    if(sendfile(fd2,fd,NULL,sb.st_size) < 0)
    {
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1;
    }
    close(fd);
    close(fd2);
    return 0;
}

splice

#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sendfile.h>


int main(int argc, char** argv) 
{
    int fd = open("/tmp/fuck",O_RDONLY | O_RDONLY);
    if(fd < 0)
    {
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1;
    }
    int fd2 = open("/tmp/fuck1",O_CREAT | O_TRUNC | O_WRONLY);
    if(fd2 < 0)
    {
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1;
    }

    struct stat sb;
    if (fstat(fd, &sb) == -1)
    {
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1;
    }
    int pipefd[2];
    if(pipe( pipefd ) < 0)
    {
        printf("[%d]%d %s\n",__LINE__,errno,strerror(errno));
        return -1;
    }

    loff_t off_out=0;
    loff_t off_in=0;
    int max_read = 4096;
    while(sb.st_size > off_in)
    {
        int toread = (sb.st_size - off_in > max_read)?max_read:sb.st_size - off_in ;
        int readlen = splice(fd, &off_in, pipefd[1], NULL, toread, SPLICE_F_MORE |SPLICE_F_MOVE);
        splice(pipefd[0], NULL, fd2, &off_out, readlen, SPLICE_F_MORE |SPLICE_F_MOVE);
    }
    close(fd);
    close(fd2);
    return 0;
}

Direct IO

在open时指定O_DIRECT标志位.

参考

  1. http://www.ibm.com/developerworks/cn/linux/l-cn-zerocopy1/
  2. https://www.ibm.com/developerworks/cn/linux/l-cn-zerocopy2/
  3. http://www.ibm.com/developerworks/cn/linux/l-cn-directio/