精华内容
下载资源
问答
  • 标准IO与系统IO的区别
    2021-08-14 09:42:49

            1.系统IO操作文件时是无缓冲输入,一般用于操作字符设备文件(LCD, LED, BEEP ...,数据需要实时刷新)

               标准IO操作文件时是有缓冲输入,一般用于操作普通文件(.txt, .jpg...)

                    缓冲机制可分3类:全缓冲, 行缓存,无缓冲

                     全缓冲:填满标准I/O缓存区才进行实际的I/O操作。(fwrite/fread)

                     行缓存:当在遇到换行符或者缓冲区满时,标准IO库执行IO系统调用操作(printf)

                     无缓冲:标准I/O库不对字符进行缓冲存储 (标准出错)


             2.系统IO是Linux操作系统提供函数接口
                标准IO标准C语言库函数提供的


            系统IO的API接口有:open  read   write  close   lseek .....

            标准IO的API接口有:fopen fread  fwrite fclose  ftell  ferror feof .....    

            系统IO个人认为操作文件比较方便点,但方便的同时也没这么精确,可以根据自己的需求而选择。标准IO比较精确, 如果想要代码更加的精确完善可以使用标准IO。可以这么理解系统IO能实现的功能,标准IO都能实现,但标准IO能实现的,系统IO未必能实现。

    更多相关内容
  • Linux系统IO与标准IO.pdf

    2018-03-09 12:31:22
    Linux系统IO与标准IO的具体使用介绍,摘自Linux 环境编程图文指南
  • 学了这么久的文件IO了,总是不知道什么时候该用系统IO,什么时候该用标准IO,今天就来整理整理,并分享出来
  • 文件中详细描述了,Linux中的文件IO内容,跟标准IO内容详解,以及两者之间的区别,并进进行了比较,新人比较容易看明白
  • 通过C语言用标准IO实现文件打复制;通过C语言用标准IO实现文件打复制;通过C语言用标准IO实现文件打复制;通过C语言用标准IO实现文件打复制;通过C语言用标准IO实现文件打复制;通过C语言用标准IO实现文件打复制;
  • 标准io流获取文件长度
  •  先来了解下什么是标准IO以及文件IO。  标准IO:标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定义,具有一定的可移植性。标准IO库处理很多细节。例如缓存分配,以优化长度...
  • C++标准IO文档

    2018-02-22 17:13:04
    C++标准IO 2 1.面向对象的标准库 2 2.流的状态 4 1.流状态 4 2.流状态的使用 4 3.缓存的管理 5 1.刷新输出缓冲区 5 2.输入和输出绑定 6 4.文件IO 6 1.类与对象 6 2.函数调用 7 1.文件模式 7 2.open函数 8 3.close...
  • 标准IO重定向和管道

    2021-02-06 21:05:47
    Linux基础入门,适合运维小白
  • 适用于编程初学者,不给你们看
  • 系统IO和标准IO

    千次阅读 2022-04-04 10:24:07
    一、系统IO和标准IO I/O:是一切实现的基础 stdio标准IO sysio系统调用IO(文件IO) stdio:FILE类型贯穿始终 sysio:fd是在文件IO中贯穿始终的类型,fd是文件描述符(整型数)

    一、系统IO和标准IO

    • I/O:是一切实现的基础
    • stdio标准IO
    • sysio系统调用IO(文件IO)

    1、stdio:FILE类型贯穿始终
    2、sysio:fd是在文件IO中贯穿始终的类型,fd是文件描述符
    文件IO与标准IO的关系
    3、文件描述符的概念:
    (1)整型数,数组的下标,文件描述符优先使用当前可用范围内最小

    二、标准IO

    (一)fopen()和fclose()

    1、fopen()

    #include <stdio.h>
    FILE *fopen(const char *path,const char *mode);

    • (1)fopen()函数返回值:是栈、静态区、堆的哪一个?
    FILE *fopen(const char *path,const char *mode)//栈上猜测
    {
        FILE  tmp; 
        tmp. = ;
        ...........
        return &tmp; 
    }
    
    FILE *fopen(const char *path,const char *mode)//静态区猜测
    {
        static FILE  tmp; 
        tmp. = ;
        ...........
        return &tmp; 
    }
    
    FILE *fopen(const char *path,const char *mode)//放在堆上
    {
        FILE  *tmp = NULL;
    
        tmp = malloc(sizeof(FILE));
        tmp-> = ;
        ...........
    
        return tmp; 
    }
    
    • 小结
      栈(F)    静态区(F)    堆(Ture)
      fopen();和fclose();是互逆操作,都是放在堆上 ———> 有互逆操作一定放在
      如果没有互逆操作的,就要自己用程序去判断是放在静态区还是堆上。
    • (2)fopen()只读方式,查看文件报错信息
    int main()
    {
       FILE *fp;
       fp = fopen("tmp","r");
       if (fp == NULL)
       {
           fprintf(stderr,"fopen() faild! errno = %d\n",errno);//errno已经被私有化
           perror("fopen()");
           fprintf(stderr, "fopen()%s\n", strerror(errno));
           exit(1);
       }
       else
       {
           fputs("ok!\n",stdout);
           fputs("OK\n",fp);
       }
       exit(0);
    }
    

    2、fclose()

    int main()
    {
       FILE *fp;
       fp = fopen("tmp","w");
       if (fp == NULL)
       {
           fprintf(stderr,"fopen() faild! errno = %d\n",errno);//errno已经被私有化
           perror("fopen()");
           fprintf(stderr, "fopen()%s\n", strerror(errno));
           exit(1);
       }
       puts("ok!");
       fclose(fp);
       exit(0);
    }
    

    3、文件打开信息

    • (1)一个进程中,默认打开3个流 stream —> stdin、stdout、stderr
    • (2)ulimit -a 控制打开的个数
    • (3)新文件权限 产生的公式: 0666(8进制) & ~umask
    • (4)umask 的值默认是0002(8进制),新建文件权限默认是:0664(8进制)
    //maxfopen(),w  查看文件最多可以打开多少个
    int main()
    {
        int count = 0;
        FILE *fp = NULL;
        
        while (1)
        {
            fp = fopen("tmp", "w");
            if (fp == NULL)
            {
                perror("fopen()");
                break;
            }
            count++;
        }
        printf("count=%d\n", count);//输出count=1021,因为默认打开3个流 stream ---> stdin stdout stderr
        exit(0);
    }
    

    4、比较文件是否相同

    • diff   文件名1   文件名2

    (二)fgetc()和fputc()

    1、fgetc()

    //这节主要讲fgetc 可以用来统计文件的大小
    int main(int argc,char **argv)
    {
       FILE *fp = NULL;
       int count = 0;
    
       if (argc < 2)
       {
           fprintf(stderr,"Usage:.....\n");
           exit(1);
       }
       fp = fopen(argv[1],"r");
       if (fp == NULL)
       {
           perror("fopen()");
           exit(1);
       }
       while(fgetc(fp) != EOF)
       {
           count++;
       }
       printf("%d\n",count);
       fclose(fp);
       exit(0);
    }
    

    2、fgetc()和fputc()联合使用

    • 通过fgetc()和fputc()函数章节,实现文件内容以字符操作方式
    int main(int argc,char **argv)
    {
       FILE *fps = NULL;
       FILE *fpd = NULL;
       int ch;
    
       if (argc < 3) //必须是3个参数
       {
           fprintf(stderr,"Usage:<s_file> <d_file>\n");
           exit(1);
       }
       
       fps = fopen(argv[1],"r");
       if (fps == NULL)
       {
           perror("fopen()");
           exit(1);
       }
       
       fpd = fopen(argv[2],"w");
       if (fpd == NULL)
       {
           fclose(fps);
           perror("fopen()");
           exit(1);
       }    
       
       while (1)
       {
           ch = fgetc(fps);
           if(ch == EOF)
           {
               break;
           }
           fputc(ch, fpd);
       }
    
       fclose(fpd);//先关目标文件,再关源文件
       fclose(fps);
       exit(0);
    }
    

    (三)fgets()和fputs()

    • 功能:实现文件内容以字符串操作方式
      1、fgets()函数详解
    //gets()函数不要使用,C基础中有讲
    //char *fgets(char *s, int size, FILE *stream);
    
    
    #define SIZE 5
    char bug[SIZE];
    fgets(buf,SIZE,stream);
    
    //fgets遇到 size-1 or '\n'停止
    
    (1)文件内容abcdef  读SIZE-1
    1  ----->  a b c d '\0'
    
    (2)文件内容ab      读SIZE-1
    2  ----->  a b '\n' '\0'
    
    (3)文件内容abcd    擦边球  用fgets(buf,SIZE,stream);来读取,读取两次
    1-> a b c d '\0'
    2-> '\n' '\0'  ....
    

    2、fgets()和fputs()函数进行读写

    #define BUFSIZE 1024
    
    int main(int argc,char **argv)
    {
        FILE *fps = NULL;
        FILE *fpd = NULL;
    
        char buf[BUFSIZE];
    
        if (argc < 3) //必须是3个参数
        {
            fprintf(stderr,"Usage:<s_file> <d_file>\n");
            exit(1);
        }
    
        fps = fopen(argv[1],"r");
        if (fps == NULL)
        {
            perror("fopen()");
            exit(1);
        }
    
        fpd = fopen(argv[2],"w");
        if (fpd == NULL)
        {
            fclose(fps);
            perror("fopen()");
            exit(1);
        }
    
        while (fgets(buf, BUFSIZE, fps) != NULL)
        {
            fputs(buf,fpd);
        }
    
        fclose(fpd);//先关目标文件,再关源文件
        fclose(fps);
        exit(0);
    }
    

    (四)fread()和fwrite()函数

    1、fread()函数详解

    • fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    • fread保险起见,size=1个字节方式读
    //1、知识点草稿
    //fread(buf, size, nmemb, fp);
    1 ---> 数据量足够  读一次   保险起见多1个字节方式  ********
    fread(buf,1,10,fp)  ---> 10个对象,读到10个字节
    fread(buf,10,1,fp)  ---> 1个对象, 读到10个字节
    
    2 ---> 只有5个字节
    fread(buf,1,10,fp)  ---> 5个对象,读到5个字节
    fread(buf,10,1,fp)  ---> 0个对象,文件剩余多少???不知道
    

    2、fread()和fwrite()函数进行读写

    #define BUFSIZE 1024
    
    int main(int argc,char **argv)
    {
        FILE *fps = NULL;
        FILE *fpd = NULL;
    
        char buf[BUFSIZE];
        int n;
    
        if (argc < 3) //必须是3个参数
        {
            fprintf(stderr,"Usage:<s_file> <d_file>\n");
            exit(1);
        }
    
        fps = fopen(argv[1],"r");
        if (fps == NULL)
        {
            perror("fopen()");
            exit(1);
        }
    
        fpd = fopen(argv[2],"w");
        if (fpd == NULL)
        {
            fclose(fps);
            perror("fopen()");
            exit(1);
        }
    
        while ((n = fread(buf, 1, BUFSIZE, fps)) > 0) //返回读到的字节数,然后写n个字节
        {
            printf("%d\n", n);
            fwrite(buf, 1, n, fpd);
        }
    
        fclose(fpd);//先关目标文件,再关源文件
        fclose(fps);
        exit(0);
    }
    

    (五)printf()和scanf()函数

    1、引申   sprintf   atoi**
    (1)atoi函数使用

    int main()
    {
        char str[] = "123a456";
    
        printf("%d\n", atoi(str));
    
        exit(0);
    }
    

    (2)sprintf函数使用

    int main()
    {
        char buf[1024];
        int y = 2022, m = 3, d = 26;
        
        sprintf(buf,"%d-%d-%d",y,m,d);
        puts(buf);
    
        exit(0);
    }
    

    (六)fseek()和ftell()函数

    1、fseek()和ftell()函数的缺陷

    • int fseek(FILE *stream, long offset, int whence);//设置文件指针位置 offset是偏移位置
    • long ftell(FILE *stream);//返回文件指针位置
    • 大小有局限性,因为long的大小在不同编译器中不确定

    (1)通过 fseek()和ftell() 两个函数可以读取 文件大小

    int main(int argc,char **argv)
    {
        FILE *fp = NULL;
        long count;
    
        if (argc < 2)
        {
            fprintf(stderr,"Usage:.....\n");
            exit(1);
        }
    
        fp = fopen(argv[1],"r");
        if (fp == NULL)
        {
            perror("fopen()");
            exit(1);
        }
    
        fseek(fp, 0, SEEK_END); //SEEK_SET, SEEK_CUR, or SEEK_END
        count = ftell(fp);
    
        printf("%ld\n",count);
        fclose(fp);
    
        exit(0);
    }
    

    2、fwind()函数

    • void rewind(FILE *stream);//使得文件指针回到文件开始位置
    • rewind是对fseek的封装:(void) fseek(stream, 0L, SEEK_SET)

    3、文件指针
    (1)何谓文件指针
         就像读书时眼睛移动一样,文件指针逐行移动
    (2)什么时候用?
         对一个文件先写后读的时候,比如:

    • FILE *fp = fopen();
    • fputc(fp); //放入10个字节,文件中有个文件位置指针,是指向最后一个字节的
    • fgetc(fp); //所以,再读取10个字节,无法得到刚刚写入的东西(指针已经向后偏移了)

    (七)fseeko()和ftello()函数的出现

    • int fseeko(FILE *stream, off_t offset, int whence);
    • off_t ftello(FILE *stream);

    1、弥补了fseek()和ftell()缺陷

    2、off_t的大小可以在makefile中加入宏定义: CFLAGS+=-D_FILE_OFFSET_BITS=64

    (八)标准IO的缓冲区和fflush()函数

    缓冲区的作用:大多数情况下是好事,合并系统调用

    1、行缓冲
         换行时候刷新,满了的时候刷新,强制刷新(标准输出都是这样的,因为是终端设备)   stdout

    2、全缓冲
    (1)满了的时候刷新,强制刷新(默认,只要不是终端设备都是全缓冲)
    (2)现在的"\n"只是起到了换行作用
    (3)缓冲区可以改的函数    setvbuf()

    int setvbuf(FILE *stream, char *buf, int mode, size_t size);
    

    3、无缓冲
         如:stderr,需要立即输出的内容

    4、缓冲区的实例说明

    (1) 缓冲区不够,不输出

    //无法输出Before while
    int main()
    {
        printf("Before while");
        while(1)
        {
            ;
        }
        printf("After while");
        exit(0);
    }
    

    (2) 行缓冲输出方式

    //末尾加换行符,可以输出Before while
    int main()
    {
        printf("Before while\n");
        while (1)
        {
            ;
        }
        printf("After while\n");
        exit(0);
    }
    

    (3)无缓冲输出方式

    //使用fflush()函数可以输出Before while
    int main()
    {
        printf("Before while");
        fflush(stdout);
        while (1)
        {
            ;
        }
        printf("After while");
        fflush(NULL);
        exit(0);
    }
    

    (九)getline()函数

    • 作用:取到完整的一行函数
    • getline()内部封装形式: malloc() realloc() realloc()…realloc()
    • getline()属于可控内存泄漏   还有不可控的内存泄漏:服务器一直运行下去
    • 使用getline()时,在makefile里面加-D_GNU_SOURCE   或者   函数里引用 #define _GNU_SOURCE
    int main(int argc, char **argv)
    {
        FILE *fp = NULL;
        char *linebuf;
        size_t linesize;
    
        if (argc < 2)
        {
            fprintf(stderr,"Usage:<s_file> <d_file>\n");
            exit(1);
        }
    
        fp = fopen(argv[1], "r");
        if(fp == NULL)
        {
            perror("fopen()");
            exit(1);
        }
    
        printf("%s——%d——%s\n", __FILE__, __LINE__, __FUNCTION__);
    
        linebuf = NULL; //加这句很重要!!!!!
        linesize = 0;   //加这句话很重!!!!!
    
        while (1)
        {
            if(getline(&linebuf, &linesize, fp) < 0)//getline()存在可控内存泄漏
            {
                break;
            }
            printf("%ld\n", strlen(linebuf));
            printf("%ld\n", linesize);
        }
    
        fclose(fp);
        exit(0);
    }
    

    (十)临时文件

    1、记住两点,①如何不冲突,②及时销毁
    (1)tmpnam()不合适,容易多个人同时拿到
    (2)tmpfile(): 合适,无文件名,不冲突,只要进程不是无休止的运行,不用fclose()也可以释放
    (3)用fclose()可以及时销毁!!!!!

    三、系统IO

    (一)open()和close()

    在这里插入图片描述

    1、文件的拷贝

    #define  BUFSIZE 1024
    
    int main(int argc, char **argv)
    {
        int sfd, dfd;
        char buf[BUFSIZE];
        int len, ret, pos;
    
        if (argc < 3)
        {
            fprintf(stderr, "Usage ....\n");
            exit(1);
        }
    
        sfd = open(argv[1], O_RDONLY);
        if (sfd < 0)
        {
            fprintf(stderr, "sfd open = %d\n", errno);
            perror("open()");
            exit(0);
        }
    
        dfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0600);
        if (dfd < 0)
        {
            close(sfd);
            fprintf(stderr, "dfd open = %d\n", errno);
            exit(0);
        }
    
        while (1)
        {
            len = read(sfd, buf, BUFSIZE);
            if(len < 0)
            {
                perror("read()");
                break;
            }
            if(len == 0)
                break;
    
            pos = 0;
            while (len > 0)
            {
                ret = write(dfd, buf + pos, len);
                if (ret < 0)
                {
                    perror("write()");
                    close(dfd);
                    close(sfd);                
                    exit(1);
                }
                pos = ret;
                len -= ret;
            }
        }
    
        close(dfd);
        close(sfd);
        exit(0);
    }
    
    //139运行测试
    //1、   ./139ReadWrite /etc/services ./out
    //2、   diff /etc/services ./out  ————> 比较文件是否一样 
    
    //140运行测试
    //1、   time    ./139ReadWrite /etc/services ./out   当前进程执行所要的时间
    //(1)运行结果:
    //      real	0m0.001s   
    //      user	0m0.001s
    //      sys	    0m0.000s
    //(2)时间:
    //      real = user + sys + (调度等待时间)
    //      程序员解决是user和sys的时间
    

    (二)文件IO与系统IO的区别

    1、举例
      快递员送快递,分拣后批量送快递、单个快递送
    2、区别
      响应速度(系统IO)&吞吐量(标准IO的缓冲区)
    3、如何使一个程序更快
      结合响应速度和吞吐量回答
    4、转换
      fileno()和fdopen()
    5、注意:标准IO与文件IO不可以混用
      (1)FILE *fp; fputc —> pos++ ; fputc —> pos++
      (2)标准IO的pos有缓冲区,pos指针移动,不会影响系统IO的pos。
        举例:word保存与不保存。
      (3)系统IO的pos是等到标准IO缓冲区满,才会使系统IO的pos指针移动
    6、通过strace  ./xxx
      strace可以用来查看一个可执行文件的系统调用

    //1、 strace ./140StdioSysioDiff  运行后可以看到标准IO存在缓冲区,最后输出项
    int main()
    {
        printf("a");
        write(1, "b", 1);
    
        printf("a");
        write(1, "b", 1);
    
        printf("a");
        write(1, "b", 1);
    
        printf("\n");
    
        exit(0);
    
    }
    
    //更好的验证stdio的缓冲区
    //2、 ./140StdioSysioDiff  可以验证ulimit -a  内容里面的数值
    //    ulimit -a中的限制open files   (-n) 1024
    
    int main()
    {
        for (int i = 0; i < 1025; i++)
        {
            printf("a");
            write(1, "b", 1);
        }
    
        printf("\n");
        exit(0);    
    }
    

    (三)IO效率问题

    1、习题
      将mycpy.c程序进行更改,将BUFSIZE的值一直放大,并观察进程所消耗的时间,注意性能最佳拐点出现时的BUFSIZE值,以及何时程序会出现问题。

    (四)文件共享

    1、多个任务共同操作一个文件或者协同完成任务
    (1)面试:写程序删除一个文件的第10行
       补充函数:truncate() / ftruncate

    (五)原子操作

    1、不可分割的操作

    • 作用: 解决竞争和冲突,比如tmpnam的操作,不是原子

    (六)程序的重定向dup和dup2

    1、dup的作用

    int dup(int oldfd); 将传入的文件描述符复制到(未使用的)最小新文件描述符

    (1)close(1)是关闭stdout流 原始办法来实现输出到文件中

    #define FNAME "./out"
    
    int main()
    {
        int fd;
    
        close(1);
    
        fd = open(FNAME, O_WRONLY | O_CREAT | O_TRUNC, 0600);
        if(fd < 0)
        {
            perror("open()");
            exit(0);
        }
    
        /********************************************/
    
        puts("hello!");
    
        exit(0);
    }
    

    (2)使用dup函数,这个程序存在两种情况,主要因为dup函数不是原子操作
     ①dup() 假设天生只有0、2,没有1,那么函数中fd本身创建好就是1
     ②旁边的兄弟也在运行,也突然创建一个,那么就到1上去了,你本身是3最多副本占据到4

    #define FNAME "./out"
    
    int main()
    {
        int fd;
    
        fd = open(FNAME, O_WRONLY | O_CREAT | O_TRUNC, 0600);
        if(fd < 0)
        {
            perror("open()");
            exit(0);
        }
    
        close(1);
        dup(fd);
        close(fd);
    
        /********************************************/
        puts("hello!");
    
        exit(0);
    }
    

    2、dup2的函数
    (1)、dup2属于原子操作方式

    //实现输出到终端信息的内容,输出到对应的文件中
    
    #define FNAME "./out"
    
    int main()
    {
        int fd;
    
        fd = open(FNAME, O_WRONLY | O_CREAT | O_TRUNC, 0600);
        if(fd < 0)
        {
            perror("open()");
            exit(0);
        }
    
        dup2(fd, 1);//相当于这两句操作:close(1);dup(fd);
    
        if (fd != 1)
        {
            close(fd);
        }      
    
        /********************************************/
        puts("hello!");
    
        exit(0);
    

    (七)同步

    1、sync设备即将解除挂载时进行全局催促,将buffer cache的数据刷新
    2、fsync刷新文件的数据,并更新文件的属性
    3、fdatasync函数只刷新文件的数据部分,而除数据外的文件属性(文件的时间)不更新

    (八)Linux的ioctl和fcntl

    1、fcntl函数
     管家级函数,文件描述符所变得魔术几乎都来源于该函数
    2、ioctl函数
     (1)设备相关的内容
     (2)ioctl_list是跟设备打交道

    (九)虚目录

    1、/dev/fd/ 显示的是当前进程的文件描述符信息
    2、ls -l /dev/fd/      看到谁就是查看谁,即在看ls

    展开全文
  • 标准IO库与QT流的使用
  • 大型自动化设备工作台标准IO配置表 - A02020_06_17
  • 标准IO:带缓存的IO,又称为标准IO(C标准库中提供了标准IO库,即stdio),它实现了跨平台的用户缓存解决方案。 文件IO 和 标准IO的概念 【文件I/O】 文件I/O是操作系统封装了一系列open、close、write、read等API...

    系统IO:Unix/Linux下的系统文件IO,即文件访问机制不经过操作系统内核的缓存,数据直接在磁盘和应用程序地址空间进行传输。

    标准IO:带缓存的IO,又称为标准IO(C标准库中提供了标准IO库,即stdio),它实现了跨平台的用户缓存解决方案。
     

    文件IO 和 标准IO的概念

    【文件I/O】

            文件I/O是操作系统封装了一系列open、close、write、read等API函数构成的一套用来读、写文件的接口供应用程序使用,通过这些接口可以实现对文件的读写操作,但是效率并不是最高的。

            文件I/O是采用系统直接调用的方式,因此当使用这些接口对文件进行操作时,就会立刻触发系统调用过程,即向系统内核发出请求之后,系统内核会收到执行相关代码处理的请求,决定是否将操作硬件资源或返回结果给应用程序。

    【标准I/O】

            标准IO:应用层C语言库函数提供了一些用来做文件读写的函数列表,叫标准IO。标准IO有一系列的C库函数构成(fopen,fclose,fwrite,fread),这些标准IO函数其实是由文件IO封装而来的(fopen内部还是调用了open);,我们通过fwrite写入的内容不是直接进入内核中的buf,而是先进入应用层标准IO库自己维护的buf中,然后标准IO库自己根据操作系统单次write的最佳count来选择好的时机来完成write到内核中的buf中。因此,标准I/O封装了底层系统调用更多的调用函数接口。

    文件I/O和标准I/O的本质区别:

            1)缓冲区:标准I/O函数接口在对文件进行操作时,首先操作缓存区,等待缓存区满足一定的条件时,然后再去执行系统调用,真正实现对文件的操作。        而文件I/O不操作任何缓存区,直接执行系统调用。

            2)系统开销:使用标准I/O可以减少系统调用的次数,提高系统效率。例如,将数据写入文件中,每次写入一个字符。采用文件I/O的函数接口,每调用一次函数写入字符就会产生一次系统调用。        而执行系统调用时,Linux必须从用户态切换到内核态,处理相应的请求,然后再返回到用户态,如果频繁地执行系统调用会增加系统的开销。

            3)执行效率:采用标准I/O的函数接口,每调用一次函数写入字符,并不着急将字符写入文件,而是放到缓存区保存,之后每一次写入字符都放到缓存区保存。直到缓存区满足刷新的条件(如写满)时,再一并将缓存区中的数据写入文件,执行一次系统调用完成此过程,这样便很大程度地减少了系统的调用次数,提高了执行效率。

     

    可以使用 time 命令测试 系统IO 和 标准IO程序执行效率,比如写 100 0000个数到某文件中。

    time命令:程序执行时加上time能够粗略统计程序执行过程中的耗时。通常会有三个值real time, user time和sys time.

    1. real time
    概念:程序从开始到结束所经历的时间,也就是用户所感受到的时间。包括当前程序CPU的用时和所有延迟程序执行的因素的耗时总和(比如其他程序耗时,等待I/O完成耗时等)。

    来源:real time是由gettimeofday()中结束时间与开始时间相减得来。

    2. user time
    概念:程序执行过程中在用户空间(user space)中所花费的所有时间,即程序用户模式下的CPU耗时。

    仅指当前进程。
    其他进程的时间和当前进程I/O阻塞的时间均不计在内。
    来源:user time是由wait()或times()系统调用得来。
    3. sys time
    概念:程序执行过程中内核空间(kernel space)中所花费的时间,即程序在内核调用中的CPU耗时。

    仅指当前进程。
    程序的库代码调用仍然是在用户空间下。
    来源:sys time是由wait()或times()系统调用得来。

    time 命令应用详解: Linux系统-real/user/sys time - kakaisgood - 博客园

            Real 是时钟时间-程序从开始至结束的总时间。他包括期间其他进程所占用的时间片和进程被阻塞的时间(如IO等待的时间)

            User 被测试程序在用户模式下所花的CPU时间。他是进程执行的正真的CPU时间。其他进程调度的时间片以及阻塞(如IO)的时间不包含在内。

            Sys 是进程在内核中所花费的CPU时间。他表示进程在内核调用中所花的CPU时间,而程序的库调用仍然运行在用户空间下。

    User+Sys表示程序所执行的CPU时间(不包括IO以及其他进程的CPU时间).

    系统IO速度快还是标准IO速度快呢

    —— 标准IO比系统IO快了好多,原因是:
    标准IO比系统IO多了一个缓存区。当我们将数据输入时,他不会马上将数据写入文件,而是会将数据先写入缓存区,之后一次性写入很多数据。而系统IO没有缓存区,所以他每次都要在数据和文件之间来回搬运所以增加了很大的工作量。

    解决方法
    手动的为系统IO加上一个缓存区,即使用dup2() 函数制定一个带缓冲区的文件描述符即可。

    系统IO和标准IO的速度对比_抹布吸的博客-CSDN博客


    #include <unistd.h>

    int dup2(int oldfd, int newfd);

    dup2可以用参数newfd指定新文件描述符的数值。若参数newfd已经被程序使用,则系统就会将newfd所指的文件关闭,若newfd等于oldfd,则返回newfd,而不关闭newfd所指的文件。dup2所复制的文件描述符与原来的文件描述符共享各种文件状态。共享所有的锁定,读写位置和各项权限或flags等

    dup()、dup2() 函数详解如下:

    linux c——dup( )和dup2( )函数详解_tiandc的博客-CSDN博客_dup2

    这里也有一篇很好的总结,记录下:系统调用IO和标准IO - 原野追逐 - 博客园

    https://www.cnblogs.com/songhe364826110/p/11546076.html

    展开全文
  • 深究标准IO的缓存

    2020-07-17 14:32:43
    在最近看了APUE的标准IO部分之后感觉对标准IO的缓存太模糊,没有搞明白,APUE中关于缓存的部分一笔带过,没有深究缓存的实现原理,这样一本被吹上天的书为什么不讲透彻呢?
  • Linux中的系统IO与标准IO

    千次阅读 多人点赞 2019-01-27 09:42:09
    一、系统IO与标准IO的区别 什么是系统IO与标准IO:(IO为Input/Output,即输入/输出接口) 系统IO:由操作系统直接提供的接口函数 标准IO:由标准C库(第三方库)提供的接口函数(通过封装操作系统提供的系统IO,...

    一、系统IO与标准IO的区别

    什么是系统IO与标准IO:(IO为Input/Output,即输入/输出接口)

    • 系统IO:由操作系统直接提供的接口函数
    • 标准IO:由标准C库(第三方库)提供的接口函数(通过封装操作系统提供的系统IO,再给用户使用)

    系统IO和标准IO的主要区别:

    • 系统IO:不带缓冲机制,系统IO可以操作普通文件与驱动文件
    • 标准IO:带缓冲机制,标准IO只可以操作普通文件。提供多种的格式的输入输出如(字符串、整形......)

    缓冲的作用与刷新条件

    • 作用:
    • 在进行数据的读写的过程中,先不把数据直接写入或者读入设备中,而是写或者读入内存空间,当满足一定条件时候,将该空间的文件写入文件或设备中。这样可以减少操作系统调用驱动程序或文件的次数,提高读写的速度,和代码的效率。因为每一次系统调用的过程都是很浪费系统资源的。

    刷新条件:

    • 缓冲区已满
    • 强制刷新
    • 程序结束
    • 关闭文件
    • 例1:
    • 系统IO与标准IO的示意图:

     

    • 例2
    • 系统IO与标准IO的区别示意图

    二、使用系统IO与标准IO的常见步骤

    设备文件:

    • open打开设备文件
    • mmap映射设备地址
    • close关闭设备文件
    • 对映射的内存操作.......

    普通文件:(若需要格式化输入输出

    • fopen打开普通文件
    • 对文件的读/写 (fscanf,fprintf,fread,fwrite........)
    • fclose关闭文件

    三、常用系统IO以及标准IO的详细参数

    注意:在使用API接口的时候,我们只要注意需要什么参数,以及参数的返回值

    一、打开文件:open 与 fopen(可以在linux中使用 man 2 open 与 man 3 fopen 查看详细手册)


    系统IO


    头文件:

    • #include <sys/types.h>
    • #include <sys/stat.h>
    • #include <fcntl.h>

    接口函数:

    • int open(const char *pathname, int flags);

    参数解析:

    • 参数一、需要打开文件的路径名(pathname)
    • 参数二、打开文件的权限请求(flags)
    • O_RDONLY,   //只读
    • O_WRONLY,   //只写
    • O_RDWR.     //读写 
    • O_CREAT//带创建打开
    • O_EXCL//检测文件是否存放
    • O_NOCTTY//以不阻塞方式打开
    • O_TRUNC//以清空方式打开  
    • O_APPEND//以追加方式打开

    返回值:

    • 成功:返回 文件描述符
    • 失败:返回 -1

    标准IO


    头文件:    

    • #include <stdio.h>

    接口函数:

    • FILE *fopen(const char *path, const char *mode);

    参数解析:

    • 参数一、需要打开的路径名(path)
    • 参数二、打开文件的权限(mode)
    • "r"  只读  
    • "r+" 读写  
    • w"  只写,带创建  :存在清空
    • "w+" 读写, 带创建  :存在清空
    • "a"  只写并追加  带创建
    • "a+" 读写并追加  带创建

     返回值:

    • 成功:返回文件指针
    • 失败:返回 NULL

    二、读取文件:read 和 fread (在linux中可以用 man 2 read 和 man 3 fread 来查看详细手册)


    系统IO


    头文件:

    • #include <unistd.h>

    接口函数:

    • ssize_t read(int fd, void *buf, size_t count);

    参数解析:

    • 参数一、文件描述符(fd)
    • 参数二、从文件读取数据后,存放的缓存地址
    • 参数三、需要读取的字节数

    返回值:

    • 成功:成功读取到的字节数
    • 失败:0 读取到的文件是0字节 或者 已经读到文件末尾
    •           -1 读取数据失败

    标准IO


    头文件:

    • #include <stdio.h>

    接口函数:

    • size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

    参数解析:

    • 参数一、存放数据的缓存地址(ptr)
    • 参数二、数据类型大小 / 数据块大小(size)
    • 参数三、多少个这样的数据(块) (nmemb)
    • 参数四、需要读取的文件指针(stream)

    返回值:

    • 成功:读取到的字节块数量(注意:不是字节数)
    • 失败:返回 0 或者 -1

    三、写入文件: write 和 fwrite (在linux中可以使用man 2 write 和 man 3 fwrite查看详细手册)


    系统IO


    头文件:

    • #include <unistd.h>

    函数接口:

    • ssize_t write(int fd, const void *buf, size_t count);

    参数解析:

    • 参数一、文件描述符(fd)
    • 参数二、需要写入文件的数据的缓存地址(buf)
    • 参数三、写入文件的字节大小(count)

    返回值:

    • 成功:成功写入的字节数
    • 失败: 返回 -1

    标准IO


    头文件:

    • #include <stdio.h>

    函数接口:

    • size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

    参数解析:

    • 参数一、需要写入的数据的缓存地址
    • 参数二、写入的数据类型大小 / 数据块大小
    • 参数三、写入数据块的数量
    • 参数四、需要写入的文件指针

    返回值:

    • 成功:返回写入数据块的个数(注意:不是字节数!)
    • 失败: 返回 -1

    五、光标移动 lseek 和 fseek (在linux中可以使用man 2 lseek 和 man 3 fseek查询详细手册)


    系统IO


    头文件:

    • #include <sys/types.h>
    • #include <unistd.h>

    接口函数:

    • off_t lseek(int fd, off_t offset, int whence);

    参数解析:

    • 参数一、文件描述符(fd)
    • 参数二、光标偏移量(offset)
    • 参数三、光标位置来源(whence)
    • SEEK_SET  文件头开始
    • SEEK_CUR  光标的当前位置开始
    • SEEK_END   从文件末尾开始

    返回值:

    • 成功:返回 偏移量的大小
    • 失败:返回 -1

    标准IO


    头文件:

    • #include<stdio.h>

    函数接口:

    • int fseek(FILE *stream, long offset, int whence);

    参数解析:

    • 参数一、文件指针(stream)
    • 参数二、光标偏移量(offset)
    • 参数三、光标位置来源(whence)
    • SEEK_SET  文件头开始
    • SEEK_CUR  光标的当前位置开始
    • SEEK_END   从文件末尾开始

    六、关闭文件


    系统IO


    头文件:

    • #include <unistd.h>

    函数接口:

    • int close(int fd);

    参数解析:

    • 参数一、文件描述符

    返回值:

    • 成功:返回 0
    • 失败:返回 -1

    标准IO


    头文件:

    • #include<stdio.h>

    函数接口:

    • int fclose(FILE *fp);

    参数解析:

    • 参数一、文件描述符(fd)

    返回值:

    • 成功:返回 0
    • 失败:返回 EOF
    展开全文
  • C语言标准IO函数整理

    2021-07-27 14:12:20
    二、常见的标准IO函数 一、简介 常见的IO函数分为两类,分别是标准IO和系统IO,具体的区别和联系为: 不同系统的系统IO有区别,而标准IO是任何平台通用的; 标准IO是依赖于系统调用IO实现的; 标准IO吞吐量大,...
  • 标准IO

    千次阅读 2018-03-09 13:54:51
    一、文件I/O和标准I/O 二、标准I/O 2.1 错误报告 2.2 流和FILE结构 2.2.1 简述 2.2.2 打开流 2.2.3 进程启动自动打开 2.2.4 FILE结构 2.3 缓冲区 2.3.1 简述 2.3.2 简单总结 2.3.3 更改缓冲类型 2.3.4 不同的缓冲...
  • 标准IO和文件IO的区别(基于Linux操作系统)
  • C | 文件IO和标准IO的区别 文件IO和标准IO各有所长。文件IO属于系统调用,是由操作系统提供的API接口,执行速度快。但频繁调用文件IO会降低内核的工作效率。不同的操作系统的API接口不同,因此造成文件IO可移植性的...
  • 标准IO:标准I/O是ANSI C建立的一个标准I/O模型,是一个标 准函数包和stdio.h头中的定义,具有一定的可移植性。标准IO库处理很多细节。例如缓存分配,以优化长度执行IO等。标准的IO提供了三种类型的缓存。 (1)全...
  • 标准IO跟系统IO

    千次阅读 2018-08-09 17:45:11
    对于操作系统而言,I/O操作可以分为两类,一类是带缓存的IO,又称为标准IO(C标准库中提供了标准IO库,即stdio),它实现了跨平台的用户缓存解决方案。另一类是Unix/Linux下的文件IO,又称直接IO,即文件访问机制不...
  • 标准IO与文件IO 的区别

    千次阅读 2017-09-05 14:15:02
    在谈两者区别之前,先来了解下什么是标准IO以及文件IO。1 定义标准IO: 标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头中的定义,具有一定的可移植性。标准IO库处理很多细节。例如缓存...
  • 标准IO 1.文件流和缓冲区 标准IO是C标准库(C语言提供的可以直接使用的库)提供的一组访问文件的函数 标准IO使用文件流(结构体指针FILE *)代表一个打开的文件,需要包含stdio.h头文件 stdio.h 49 typedef struct _IO_...
  • 浅析文件IO和标准IO

    2022-04-03 13:13:17
    目录 ...3.IO的种类:文件IO:系统调用 标准IO:系统调用+缓冲区 4.系统调用:从用户空间进入到内核空间的一个过程,操作系统不同,接口也就不同,效率低,只要系统发生调用,就要调用一次内核 5....
  • 标准IO和文件IO_01.jpg

    2020-02-02 01:55:04
    嵌入式学习笔记(一)——标准IO与文件IO !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!...
  • 实际上,标准IO最终还是通过调用系统提供的不带缓存的IO实现的(每次read/write都进行一次系统调用),标准IO的引入,避免了频繁的系统调用,减少了系统资源消耗,提高了IO效率。 以fgetc/fputc 为例,当用户程序第一...
  • 系统IO跟标准IO的联系与区别

    千次阅读 2018-05-30 14:54:31
    一、 什么是系统IO和标准IO 系统IO:系统IO又称文件IO,也称低级磁盘...标准IO标准IO被称为高级磁盘IO,标准IO提供三种类型的缓存:u 全缓存:当填满标准IO缓存后才进行实际的IO操作u 行缓存:当输入或输出中遇到...
  • 标准IO与文件IO

    千次阅读 2016-12-30 16:34:21
    对于操作系统而言,I/O操作可以分为两类,一类是带缓存的IO,又称为标准IO(C标准库中提供了标准IO库,即stdio),它实现了跨平台的用户缓存解决方案。另一类是Unix/Linux下的文件IO,又称直接IO,即文件访问机制不...
  • C++三大IO流类总结——标准IO流、文件IO流、内存IO流 IO流类一览标准IO标准IO流的条件状态条件状态标志条件状态函数标准IO流的输入输出成员函数代码示例条件状态put和get函数getline函数标准IO的格式控制输出格式...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 451,559
精华内容 180,623
关键字:

标准IO

友情链接: san.rar