当前位置: 首页 > wzjs >正文

网站设计入门百度账户

网站设计入门,百度账户,专业的龙岗网站建设,网站进行诊断目录 一、什么是缓冲区 二、为什么要引入缓冲区机制 三、缓冲类型 四、FILE 简单设计一下libc库 一、什么是缓冲区 缓冲区是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分…

目录

一、什么是缓冲区

二、为什么要引入缓冲区机制

三、缓冲类型

四、FILE

简单设计一下libc库


一、什么是缓冲区

缓冲区是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。

二、为什么要引入缓冲区机制

读写文件时,如果不会开辟对文件操作的缓冲区,直接通过系统调用对磁盘进行操作(读、写等),那么每次对文件进行一次读写操作时,都需要使用读写系统调用来处理此操作,即需要执行一次系统调用,执行一次系统调用将涉及到CPU状态的切换,即从用户空间切换到内核空间,实现进程上下文的切换,这将损耗一定的CPU时间,频繁的磁盘访问对程序的执行效率造成很大的影响。

为了减少使用系统调用的次数,提高效率,我们就可以采用缓冲机制。比如我们从磁盘里取信息,可以在磁盘文件进行操作时,可以一次从文件中读出大量的数据到缓冲区中,以后对这部分的访问就不需要再使用系统调用了,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大 快于对磁盘的操作,故应用缓冲区可大 提高计算机的运行速度。 

又比如,我们使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU可以处理别的事情。可以看出,缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。

三、缓冲类型

标准I/O提供了3种类型的缓冲区。

• 全缓冲区:这种缓冲方式要求填满整个缓冲区后才进行I/O系统调用操作。对于磁盘文件的操作通
常使用全缓冲的方式访问。
• 行缓冲区:在行缓冲情况下,当在输入和输出中遇到换行符时,标准I/O库函数将会执行系统调用操作。当所操作的流涉及一个终端时(例如标准输入和标准输出),使用行缓冲方式。因为标准I/O库每行的缓冲区长度是固定的,所以只要填满了缓冲区,即使还没有遇到换行符,也会执行I/O系统调用操作,默认行缓冲区的大小为1024。
• 无缓冲区:无缓冲区是指标准I/O库不对字符进行缓存,直接调用系统调用。标准出错流stderr通常是不带缓冲区的,这使得出错信息能够尽快地显示出来。

除了上述列举的默认刷新方式,下列特殊情况也会引发缓冲区的刷新:
1. 缓冲区满时;
2. 执行flush语句;

示例如下:

关闭文件描述符1,也就是让本该写入显示器,现在写入文件。相当于重定向。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main() 
{close(1);int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);if (fd < 0) {perror("open");return 0;} printf("hello world: %d\n", fd);close(fd);return 0;
}

 但是没有内容,说明语言层面的缓冲区并没有写满所有不刷新。

这是由于我们将1号描述符重定向到磁盘文件后,缓冲区的刷新方式成为了全缓冲。而我们写入的内容并没有填满整个缓冲区,导致并不会将缓冲区的内容刷新到磁盘文件中。怎么办呢?可以使用fflush强制刷新下缓冲区

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main() 
{close(1);int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);if (fd < 0) {perror("open");return 0;} printf("hello world: %d\n", fd);fflush(stdout);close(fd);return 0;
}

四、FILE

FILE结构体是 C 标准库中用于处理文件操作的一个重要数据结构,它包含了许多与文件操作相关的信息和状态,其中就包括对缓冲区的管理信息。当使用标准 I/O 函数(如fopen、fread、fwrite等)进行文件操作时,FILE结构体负责记录缓冲区的状态、位置、大小等信息,以实现对文件数据的缓冲处理,从而提高 I/O 操作的效率。


• 因为IO相关函数与系统调用接口对应,并且库函数封装系统调用,所以本质上,访问文件都是通过fd访问的。
• 所以C库当中的FILE结构体内部,必定封装了fd。

来段代码在研究一下:

#include <stdio.h>
#include <string.h>
int main()
{const char *msg0="hello printf\n";const char *msg1="hello fwrite\n";const char *msg2="hello write\n";printf("%s", msg0);fwrite(msg1, strlen(msg0), 1, stdout);write(1, msg2, strlen(msg2));fork();return 0;
}

运行出结果:

hello printf
hello fwrite
hello write

 但如果对进程实现输出重定向呢? ./hello > file ,我们发现结果变成了:

hello write
hello printf
hello fwrite
hello printf
hello fwrite

我们发现printf 和fwrite (库函数)都输出了2次,而 write 只输出了一次(系统调用)。为什么呢?肯定和fork有关! 

• 一般C库函数写入文件时是全缓冲的,而写入显示器是行缓冲。
• printf fwrite 库函数+会自带缓冲区(进度条例子就可以说明),当发生重定向到普通文件时,数据的缓冲方式由行缓冲变成了全缓冲。
• 而我们放在缓冲区中的数据,就不会被立即刷新,甚至fork之后
• 但是进程退出之后,会统一刷新,写入文件当中。
• 但是fork的时候,父子数据会发生写时拷贝,所以当你父进程准备刷新的时候,子进程也就有了同样的一份数据,随即产生两份数据。
• write 没有变化,说明没有所谓的缓冲。

综上: printf fwrite 库函数会自带缓冲区,而 write 系统调用没有带缓冲区。另外,我们这里所说的缓冲区,都是用户级缓冲区。其实为了提升整机性能,OS也会提供相关内核级缓冲区,不过不再我们讨论范围之内。

那这个缓冲区谁提供呢? printf fwrite 是库函数, write 是系统调用,库函数在系统调用的“上层”, 是对系统调用的“封装”,但是write 没有缓冲区,而 printf fwrite 有,足以说明,该缓冲区是二次加上的,又因为是C,所以由C标准库提供。

如果有兴趣,可以看看FILE结构体:

typedef struct _IO_FILE FILE;    (在/usr/include/stdio.h)

在/usr/include/libio.h
struct _IO_FILE {int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags
//缓冲区相关 /* The following pointers correspond to the C++ streambuf protocol. *//* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */char* _IO_read_ptr; /* Current read pointer */char* _IO_read_end; /* End of get area. */char* _IO_read_base; /* Start of putback+get area. */char* _IO_write_base; /* Start of put area. */char* _IO_write_ptr; /* Current put pointer. */char* _IO_write_end; /* End of put area. */char* _IO_buf_base; /* Start of reserve area. */char* _IO_buf_end; /* End of reserve area. *//* The following fields are used to support backing up and undo. */char *_IO_save_base; /* Pointer to start of non-current get area. */char *_IO_backup_base; /* Pointer to first valid character of backup area */char *_IO_save_end; /* Pointer to end of non-current get area. */struct _IO_marker *_markers;struct _IO_FILE *_chain;int _fileno; //封装的⽂件描述符 
#if 0int _blksize;
#elseint _flags2;
#endif_IO_off_t _old_offset; /* This used to be _offset but it's too small. */
#define __HAVE_COLUMN /* temporary *//* 1+column number of pbase(); 0 is unknown. */unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];/* char* _save_gptr; char* _save_egptr; */_IO_lock_t *_lock;#ifdef _IO_USE_OLD_IO_FILE
};

简单设计一下libc库

my_stdio.h

#pragma once
#include<stdio.h>
#define MAX 1024
#define NONE_FLUSH (1<<0)
#define LINE_FLUSH (1<<1)
#define FULL_FLUSH (1<<2)typedef struct _IO_FILE
{int fileno;//文件描述符int flag;//文件打开方式char outbuffer[MAX];//缓冲区大小int bufferlen;//缓冲区有效元素int flush_method;//刷新方式
}Myfile;Myfile* MyFopen(const char* path,const char* mode);//打开文件
void MyClose(Myfile*file);//关闭文件
int Mywrite(Myfile*file,void* str,int len);//向文件内写
void MyFFlush(Myfile*file);//刷新文件到输出流

my_stdio.c

#include "my_stdio.h"
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>  // 为了使用 close 和 write 等函数// 打开语言层的文件缓冲区
static MyFile* BuyFile(int fd, int flag) {MyFile* f = (MyFile*)malloc(sizeof(MyFile));if (f == NULL) {return NULL;}f->fileno = fd;f->flag = flag;f->bufferlen = 0;  // 初始化缓冲区长度为 0memset(f->outbuffer, 0, sizeof(f->outbuffer));return f;
}// 打开系统文件
MyFile* MyFopen(const char* path, const char* mode) {int fd = -1;int flag = 0;if (strcmp("w", mode) == 0) {flag = O_CREAT | O_WRONLY | O_TRUNC;  // 打开文件的方式fd = open(path, flag, 0666);  // 文件描述符} else if (strcmp("a", mode) == 0) {flag = O_CREAT | O_WRONLY | O_APPEND;fd = open(path, flag, 0666);} else if (strcmp("r", mode) == 0) {flag = O_RDWR;fd = open(path, flag);  // 只读模式不需要指定文件权限} else {// TODO}if (fd < 0) {return NULL;}return BuyFile(fd, flag);  // 调用 BuyFile 函数创建并初始化 MyFile 结构体
}// 向文件写入数据
int MyFwrite(MyFile* file, void* str, int len) {memcpy(file->outbuffer + file->bufferlen, str, len);  // 把内容写入到语言层的文件缓冲区file->bufferlen += len;if ((file->flush_method & LINE_FLUSH) && file->outbuffer[file->bufferlen - 1] == '\n') {MyFFlush(file);  // 把语言层文件缓冲区的内容刷新到系统}return len;  // 返回写入的字节数
}// 关闭文件
void MyFclose(MyFile* file) {if (file->fileno < 0) return;MyFFlush(file);close(file->fileno);free(file);
}// 刷新缓冲区
void MyFFlush(MyFile* file) {if (file->bufferlen <= 0) return;int n = write(file->fileno, file->outbuffer, file->bufferlen);  // 把语言层的内容通过系统接口写到系统if (n > 0) {fsync(file->fileno);  // 确保数据写入磁盘}file->bufferlen = 0;  // 清空缓冲区
}

本篇完,下篇见!


文章转载自:

http://Ct2ds8lF.mzbyL.cn
http://bcqcK7mM.mzbyL.cn
http://k2rOl7Pc.mzbyL.cn
http://n7HHFzDW.mzbyL.cn
http://FihvIs3W.mzbyL.cn
http://MuN8zQXf.mzbyL.cn
http://FQZECNto.mzbyL.cn
http://o5wLbDxH.mzbyL.cn
http://34B8AZoB.mzbyL.cn
http://hSzfCw9Z.mzbyL.cn
http://JZCrNz48.mzbyL.cn
http://18HcuBCg.mzbyL.cn
http://pnCIC57m.mzbyL.cn
http://H5xir8md.mzbyL.cn
http://yl86tCb1.mzbyL.cn
http://extCEeyq.mzbyL.cn
http://wtiAgb6E.mzbyL.cn
http://FfpnXmaU.mzbyL.cn
http://ecGNLKhC.mzbyL.cn
http://L0Vc8qcK.mzbyL.cn
http://DRYNlSn4.mzbyL.cn
http://Ry0hqaVx.mzbyL.cn
http://7FFlgwF2.mzbyL.cn
http://vV7GEJvm.mzbyL.cn
http://ezv8N0Vf.mzbyL.cn
http://04LmVB2y.mzbyL.cn
http://d01F7Hx5.mzbyL.cn
http://r6yddUTd.mzbyL.cn
http://cwwEIxSt.mzbyL.cn
http://utOmlBDJ.mzbyL.cn
http://www.dtcms.com/wzjs/728024.html

相关文章:

  • 广东佛山网站建设上海建设网站便宜的
  • 环宇网站建设上海平台网站开发
  • 新闻类的网站如何做优化、深圳网站建设方案外包
  • 最全的游戏网站网站建设管理典型经验材料
  • 网页模板下载网站10亚马逊雨林动物大全
  • 医药类网站建设评价网站规划与设计课程设计
  • 知名网站建设开发贺州市住房和城乡建设局网站
  • 旭泽建站搜索引擎推广seo
  • 校友网站建设的重要性销售类wordpress
  • 怎么做flash网站运动网站源码
  • wordpress手机显示图片江苏网站建设seo优化
  • wordpress 三站合一快速搭建网站的好处
  • 做金融网站需要什么营业执照家用电脑可以做网站服务器
  • 专业网站建设网站建设销售技巧
  • 炫酷的html5网站京东网站怎么做
  • 外贸公司 网站程序员网站
  • 网站中的游戏是怎么做的wordpress免费网站模板
  • 手机移动端网站做多大企业网站建设公司郑州
  • 个人网站做得优秀的深圳十大穷人区
  • 奢侈品+网站建设方案微信微商城怎么做
  • 建设教育工程网站重庆网站建设是什么
  • 1千万人网站维护成本群晖手动安装wordpress
  • 二手商品交易网站开发做加工都在哪个网站推广
  • 关于校园网站建设的建议装潢设计费用怎么算
  • 淘宝客网站还可以做吗手机如何建立网站步骤
  • 泸州市往建局建设银行网站名称中信建设有限责任公司龙芳
  • 设计制作网站的公司seo搜索优化工程师招聘
  • 临沂建手机网站公司人力外包项目发布平台
  • 信息时代网站建设的重要性辽宁建设工程信息网查
  • 上海网站推广公司排名郑州建设工程信息网站