代码之家  ›  专栏  ›  技术社区  ›  Jaiveer

读写工作流程。使用readv和writev而不是使用read和write有哪些优点?

  •  1
  • Jaiveer  · 技术社区  · 6 年前

    我只是想使用readv()从文件中获取一些数据。但总是打印垃圾字符。我试着给iovec分配空间。iov\u基地,但那里运气不好。我甚至有了一个想法,为什么要使用readv函数,而不是仅仅坚持使用更简单、可读性更强的read函数。现在,我对readv和writev函数的需求感到困惑。

        #include<stdio.h>
        #include<stdlib.h>
        #include<unistd.h>
        #include<unistd.h>
        #include<fcntl.h>
        #include<string.h>
        #include<errno.h>
        #include<sys/uio.h>
        #include<sys/types.h>
        #include<sys/stat.h>
        #define MAX 50000
        int main()
        {
            struct iovec data[2];
            int i=0,fd;
            for(i=0; i<3 ; i++ )  {
                data[i].iov_len=MAX;
                data[i].iov_base=(char*) malloc(MAX); //if this line is in comment, segmentation fault will occur. 
                /* data[i].iov_base=(char*) malloc(0); //This is also working ?*/
            }
            fd=open("/tmp/test",O_RDWR);
            if(fd==-1){
                printf("can't open the input file\n");
                return 1;
            }
            readv(fd,data,3);
            for(i=0; i<2 ; i++ )  {
                printf("((%s))\n",(char*)data[i].iov_base);
            }
        }
    

    提前谢谢你。

    1 回复  |  直到 4 年前
        1
  •  3
  •   Jonathan Leffler vy32    6 年前

    您使用POSIX readv() writev() 函数(“分散读取”和“聚集写入”另请参见 Vectored I/O )当您使用文件描述符并需要对不同(非连续)内存位置集合的读写进行分组,但希望通过单个函数调用完成读写时。

    例如,我有一个程序需要记录一些控制数据和一些二进制数据的十六进制转储,但它希望确保其写入是原子的。我有一个这样的函数:

    static void log_message(int log_fd, const char *elapsed, const char *tag, const char *buffer, ssize_t nbytes)
    {
        char hdrbuff[64];
        struct iovec vector[3];
        const char *data = format_image(buffer, nbytes);
    
        snprintf(hdrbuff, sizeof(hdrbuff), "%s %s %6ld\n", elapsed, tag, (long)nbytes);
    
        vector[0].iov_base = hdrbuff;
        vector[0].iov_len  = strlen(hdrbuff);
        vector[1].iov_base = CONST_CAST(char *, data);
        vector[1].iov_len  = strlen(data);
        vector[2].iov_base = "\n";
        vector[2].iov_len  = 1;
        if (writev(log_fd, vector, 3) <= 0)
            err_syserr("Failed to write log entry (%s: %ld)\n", tag, (long)nbytes);
    }
    

    需要写这句新词有点麻烦,但是 format_image() 函数无法添加错误的换行符。(这是一个在其他地方使用的库函数,如果它添加了一个额外的换行符,这些其他用途将被破坏。)然而 writev() 允许我在不更改库函数的情况下编写所有内容,并最大限度地提高文件上没有任何交错的可能性。(在上下文中,还有第二个进程使用相同的日志文件和相同的打开文件描述,但协议是半双工的,因此时间重叠的可能性很小。但是,使用分散/聚集I/O可以最大限度地减少出现问题的机会。)

    我没有使用 readv() 我记得,但当您知道有多个固定大小的数据块要读取到非连续内存位置时,就会使用它。