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

天元建设集团有限公司工程谁的网站模板利于优化

天元建设集团有限公司工程,谁的网站模板利于优化,h5网站设计方案,深圳自助建站系统目录 九.文件描述符 9.1 文件描述符概念 9.2 文件描述符的分配规则 9.3 重定向 9.3.1 常见的重定向操作 9.3.2 重定向的原理 9.4 缓冲区 9.4.1 缓冲区概念 9.4.2 缓冲区刷新策略 9.4.3 C语言的缓冲区在哪里? 九.文件描述符 9.1 文件描述符概念 在上一篇讲到基础IO时,我们说到…目录 九.文件描述符 9.1 文件描述符概念 9.2 文件描述符的分配规则 9.3 重定向 9.3.1 常见的重定向操作 9.3.2 重定向的原理 9.4 缓冲区 9.4.1 缓冲区概念 9.4.2 缓冲区刷新策略 9.4.3 C语言的缓冲区在哪里? 九.文件描述符 9.1 文件描述符概念 在上一篇讲到基础IO时,我们说到open函数在打开一个文件后有一个int类型的返回值.我们将之称为文件描述符. 那么到底什么是文件描述符?它有什么作用呢? 概念: 文件描述符File Descriptor,简称fd,是一个用于标识和操作文件或输入/输出设备的整数。在Unix-like操作系统中包括Linux文件描述符是对打开文件或I/O设备的引用.每个进程都有一个文件描述符表它是一个数组其中包含了该进程打开的文件或I/O设备的引用 也就是说:每一个进程都会维护一个独立的文件描述符表File Descriptor Table用来管理自己打开的文件 这个文件描述符表存储在哪里? 这里我们可以结合之前的知识猜到,文件描述表应该存储在进程的PCB结构中. 事实上,也确实如此.如上图所示,在进程对应的的task_struct结构中会存在一个files指针指向指向一个files_struct结构体 每个进程都会有单独维护的files_struct结构体,其专门用于跟踪对应进程与文件相关的信息. files_struct有两个地方来管理所有打开的文件结构即有两个数组来管理所有打开的文件结构 files_struct结构体中会包含一个struct fdtable *fdt,其指向fdtable(文件描述符表),fdtable同样也是一个结构体,其中包含** struct file fd,这个数组存储了每个文件描述符对应的文件指针files_struct结构体中同样直接包含了一个fd_array用来直接存储了每个文件描述符对应的文件指针 在这两个数组中都储存着指向file结构体的指针,也就是说进程打开的文件在内核中会被描述为struct file结构体的实例,这个结构体包含了有关打开文件的各种信息包括文件的状态、位置、访问模式等 总的来说,通过这种方式,内核能够更灵活地管理文件,而进程则通过文件描述符引用这些文件实例,而不必直接关心底层的文件结构和操作.这提供了一种高层次的抽象,简化了用户空间程序对文件的操作 在这里我们可以通过一步一步讲解fwrite()的运行过程,自上而下的梳理一遍 当我们在调用了fwrite()时,首先需要接收一个FILE *指针,表示要写入的文件的FILE结构,而对应的FILE结构体中存有文件描述符(fd),这个时候fwrite()会底层调用write(fd,.....),来执行操作系统内部的write(),它能找到进程的task_struct,再通过里面的files指针再找到files_struct,而files_struct中的fd_array[fd]便指向打开的文件的file结构体,这时候便内存文件便找到了,也就可以后续操作. 注意: 文件的fd实际上是fd_array数组的对应下标C语言中的FILE结构体和内核中的file结构体是两个不同的概念,需要区分 9.2 文件描述符的分配规则 在上文讲到基础IO时,我们讲到C语言的程序会默认打开三个流,分别是stdin,stdout,stderr. 这时候结合Linux系统的设计哲学:一切皆文件,我们可以知道,在C语言编写的程序运行后,会默认打开对应的三个文件 这时候,我们可以编写下面这个简单的程序来验证. 也就是说fd_array数组当中下标为0、1、2的位置已经被占用了,之后打开的文件都是重3之后开始 那么如果我们在进行文件操作之前将默认打开的文件关掉会怎么样呢? 这里我们将下标为1的文件先关掉进行验证,给程序先加上这样一句代码: close(0); 这时候我们再此运行观察 这时我们可以得出 文件描述符的分配规则: 顺序分配 一般情况下文件描述符会按照顺序分配即从最小的未使用的整数开始分配 9.3 重定向 9.3.1 常见的重定向操作 重定向是指将一个文件描述符与另一个文件描述符或文件关联起来从而改变输入或输出的方向。在 Unix-like 操作系统中包括 Linux重定向是一种强大的机制允许在命令行中灵活地管理输入和输出。 以下是常见的重定向操作符 1.输出重定向         示例command output.txt         描述将命令的标准输出重定向到文件 output.txt 中。如果文件不存在则会创建文件如果文件已存在将会覆盖其中的内容。 2.追加输出重定向         示例command output.txt         描述将命令的标准输出追加到文件 output.txt 中。如果文件不存在则会创建文件如果文件已存在内容将会被追加到文件末尾。 3.输入重定向         示例command input.txt         描述将文件 input.txt 中的内容作为命令的标准输入。命令将读取文件的内容而不是从键盘读取。 4.|管道         示例command1 | command2         描述将 command1 的标准输出通过管道传递给 command2 的标准输入。这使得两个命令可以协作处理数据。 5.2错误输出重定向         示例command 2 error.txt         描述将命令的错误输出重定向到文件 error.txt 中。类似于 但是针对错误输出。 6. 或 合并输出和错误输出重定向         示例command output_and_error.txt 或 command output_and_error.txt         描述将命令的标准输出和错误输出合并并重定向到文件 output_and_error.txt 中。 9.3.2 重定向的原理 重定向的本质是通过操作系统提供的文件描述符机制动态地改变进程的输入和输出源 dup2: #includeunistd.h  int dup2(int oldfd, int newfd); 函数返的作用:dup2的作用是将 newfd 指向的文件描述符关闭然后将 oldfd 复制到 newfd使得它们指向同一个打开的文件、套接字或管道。如果 newfd已经打开dup2 会首先关闭它 这个系统调用的主要应用场景之一是在重定向中将一个文件描述符重定向到另一个文件描述符。例如在 shell 命令中使用 这样的操作符进行输出重定向时实际上就是使用了dup2 函数返回值: dup2如果调用成功返回newfd否则返回-1。 使用dup2时我们需要注意以下两点 如果oldfd不是有效的文件描述符则dup2调用失败并且此时文件描述符为newfd的文件没有被关闭。如果oldfd是一个有效的文件描述符但是newfd和oldfd具有相同的值则dup2不做任何操作并返回newfd。 借助dup2(),我们可以试着模拟一下重定向的过程 #include stdio.h #include unistd.h #include fcntl.h int main() {int fd open(log.txt, O_CREAT | O_RDWR,0666);if (fd 0) {perror(open);return 1;}close(1);dup2(fd, 1);for (;;) {char buf[1024] { 0 };ssize_t read_size read(0, buf, sizeof(buf) - 1);if (read_size 0) {perror(read);break;}printf(%s, buf);fflush(stdout);}return 0; } 通过这样一个简单的程序我们便可以将标准输出文件描述符1重定向到一个文件log.txt并不断地从标准输入文件描述符0读取数据然后将其写入到文件中. 9.4 缓冲区 9.4.1 缓冲区概念 缓冲区Buffer是计算机系统中常见的概念它是一块用于临时存储数据的内存区域。缓冲区在各种计算机应用中都起着关键作用从文件输入输出到网络通信都涉及到对数据的缓冲和管理 下面是缓冲区的常见作用: 提高效率 缓冲区的存在可以减少对底层资源的频繁访问从而提高数据传输的效率。通过按块读写数据而不是逐个字节进行操作可以减少读写次数降低系统开销 平滑数据流 缓冲区可以平滑数据流使得数据以块的形式传输。这对于文件输入输出、网络通信等场景特别有用有助于减少频繁的小规模数据传输提高整体性能 优化磁盘和网络访问 在文件系统中文件缓冲区可以优化磁盘访问减少磁盘I/O的次数。在网络通信中网络缓冲区可以优化数据在网络上传输的效率 应对不同速度的设备 缓冲区可以协调不同速度的设备之间的数据传输确保数据能够以适当的速率流动避免了生产者和消费者之间的速度不匹配问题 提高用户体验 输入缓冲区允许用户按块输入数据提高了用户体验。输出缓冲区允许程序按块输出数据减少对屏幕或文件的频繁写入提高了响应速度 支持流式处理 缓冲区使得数据能够以流式的方式进行处理而不是一次性处理整个数据集。这对于处理大数据或实时数据流非常重要 适应不同工作负载 缓冲区的存在使得系统能够更好地适应不同的工作负载。它可以根据需要动态调整缓冲策略以满足不同场景下的性能需求 错误处理 缓冲区可以提供一定程度的错误处理机制。例如在网络通信中如果无法立即发送所有数据缓冲区可以保存部分数据等待合适的时机重新发送 9.4.2 缓冲区刷新策略 C语言中一般有以下几种缓冲区刷新策略: 行缓冲Line Buffering:在行缓冲模式下缓冲区在遇到换行符 \n 时自动刷新。也就是说当遇到换行符时缓冲区中的数据会被立即写入文件 全缓冲Fully Buffered:在全缓冲模式下缓冲区满时会触发刷新,此时缓冲区中的数据才会被写入文件 手动刷新缓冲区:使用 fflush() 函数手动刷新缓冲区。这对于确保数据在特定时刻被写入文件很有用 关闭文件时刷新:当文件关闭时C库会自动刷新缓冲区 一般而言行缓冲的设备文件 --- 显示器 全缓冲的设备文件 --- 磁盘文件 极端情况你是可以自定义规则的 --- 这时候我们可以自己使用fflush()来手动刷新 但所有的设备永远倾向于全缓冲 -- 缓冲区满了再刷新 -- 需要更少次数的IO操作 --更少次数的外设访问(相当于提高了整机效率). 有同学可能有疑问比如10行数据每一行有100个字节虽然10行最后再一起刷新只进行了一次的外设访问但是数据量很多啊1000个字节而按行刷新虽然刷新了10次但每次数据量少啊那为什么外设访问次数越少越好呢 这是因为和外部设备IO的时候数据量的大小不是主要矛盾你和外设预备IO的过程是最耗费时间的. 9.4.3 C语言的缓冲区在哪里? 缓冲区在哪里?我们所说的这个缓冲区是由操作系统维护还是语言维护? 为了回答这个问题,我们可以先感受下面这段代码 #includestdio.h #includefcntl.h #includesys/stat.h #includesys/types.h #includeunistd.h #includestring.h int main() {//C语言提供的接口 printf(hello,printf\n);fprintf(stdout, hello,fprintf\n);const char* s hello,fputs\n;fputs(s, stdout);//系统接口 const char* ss hello,write\n;write(1, ss, strlen(s));//创建子进程fork(); } 当我们把代码编译运行后: 此时当我们将程序的输出 重定向到另外的文件时 这时候我们可以先预测一下输出的结果 最后我们会惊讶的发现一个现象:所有C语言提供的函数都输出了两次 .而系统接口的只输出了一次 这时候我们改一下我们原本的代码,在write()与fork()之间加上一句fflush() 这时候再进行一次上述操作 这次我们发现结果又发生了变化,这是为什么呢? 这时候我们得回到最初的问题:缓冲区是由操作系统维护还是语言维护? 这时大家也许会猜到 我们所说的这个 缓冲区其实是由C语言自己维护的 在源代码中你可以找到stdio.h 头文件以及其中包含的FILE结构体的定义,而FILE结构体里面不仅封装了fd而且包含了该文件对应的语言层的缓冲区结构_IO_FILE。 _IO_FILE的内部结构大致如下 /* In glibc, FILE is a typedef, defined in FILE struct and definedelsewhere. */ struct _IO_FILE {int _flags; /* High-order word is _IO_MAGIC; rest is flags. *//* The following pointers correspond to the C streambuf protocol. */char *_IO_read_ptr; /* Current read pointer */char *_IO_read_end; /* End of get area. */char *_IO_read_base; /* Start of putbackget 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;int _flags2;__off_t _old_offset; /* This used to be _offset but its too small. *//* 1column number of pbase(); 0 is unknown. */unsigned short _cur_column;signed char _vtable_offset;char _shortbuf[1];_IO_lock_t *_lock;__off64_t _offset;/* Wide character stream stuff. */struct _IO_codecvt *_codecvt;struct _IO_wide_data *_wide_data;struct _IO_FILE *_freeres_list;void *_freeres_buf;size_t __pad5;int _mode;/* Make sure we dont get into trouble again. */char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)]; };回到我们的最初的代码 我们直接运行程序是向显示器中打印采用的是行刷新策略而我们重定向到文件中向文件中打印便成了全缓冲策略. 1.如果是向显示器中打印那么采用的是行刷新策略那么最后执行fork的时候所有的数据都已经刷新完成了此时再执行fork就没有意义了. 2.如果对程序进行了重定向即此时要向文件中打印此时刷新策略便隐式的变成了全缓冲 遇到\n换行符便不会再触发刷新. fork的时候一定是函数已经执行完了但是数据还没有刷新 这些数据在当前进程对应的C标准库中的缓冲区里. 而这些数据是父进程的. fork之后子进程和父进程执行return 0前,父进程和子进程实际上是共享相同的缓冲区的.但是当子进程执行 return 0 后由于任一方进程退出时触发了关闭文件时刷新策略此时可能触发了对标准输出缓冲区的刷新.这时写时复制拷贝机制会起作用确保子进程得到自己的缓冲区副本从而避免对父进程缓冲区的影响。这样就有了两份数据然后分别输出到文件中。 所以就出现了C语言标准库输出的函数打印了两次而系统接口打印了一次。 因为系统接口是直接写入到了文件中而不用经过缓冲区。 而在我们更改之后的代码中,fflush已经强制将缓冲区的内容刷新了出来此时缓冲区已经是空的了然后再执行fork父子进程缓冲区都是空的所以也没有数据刷新了这样才各自只打印了一条语句 此时更加让我们确信了一个事实缓冲区一定不是操作系统提供的而是由C语言标准库提供的因为如果是操作系统提供的那么这个系统接口也应该输出两次而不是只有一次 注意: 缓冲区的概念并不是特定于 C 语言而是一种广泛应用于计算机科学和编程的概念。缓冲区是一块用于临时存储数据的内存区域其目的是提高数据传输的效率。在不同的编程语言和操作系统中都存在类似的概念
http://www.yutouwan.com/news/116961/

相关文章:

  • 英文网站建设中百度浏览器入口
  • 兰州交通发展建设集团公司网站建设摩托车官网报价及图片
  • 做网站题材同步修改 wordpress
  • 公司网站转微信小程序做电商网站用什么语言
  • 瑞安网站四川省建设厅
  • 南京新标特企业网站哪家广告做的wordpress标签后缀名html
  • 网站毕业设计代做公司管理系统是系统软件吗
  • 查找做影评的工作网站淮北市建筑
  • 运输网站建设网店美工设计实训步骤
  • 自己建设网站赚钱网站推广成功案例
  • 海城区建设局网站一个微信小程序要多少钱
  • 秦皇岛网站设计制作石家庄369招聘信息网
  • 怎么用lls做网站导航网站 php
  • 万江区网站建设在北京注册公司有什么好处
  • 网站建站方式有哪些app开发做网站
  • 做网站去哪里找客户广安市城乡建设规划局网站
  • 网站视频制作五河网站建设哪家好
  • 什么主题的网站容易做点备案网站的黑名单
  • 阿里云网站备案入口湖北省建设信息港网站
  • 建设银行镇海支行网站奉贤注册公司
  • 网站建设服务哪家好 价格多少钱天津大型网站建设风格
  • 制作钓鱼网站教程什么叫做网络营销
  • 做网站如何语音对话市场营销策略是什么
  • 怎样建设公司的网站5118站长网站
  • 行业信息网站企业建站程序有哪些
  • 建网站的公司哪里好网络营销包括什么内容
  • 国外php网站源码深圳网站建设公司哪家
  • 网站经营与建设黑糖主题2.0wordpress
  • 学院网站源码外贸电子商务网站建设平台
  • 汽车门户网站 源码企业管理咨询服务合同模板