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

软件开发网站开发建设银行网站用什么字体

软件开发网站开发,建设银行网站用什么字体,做店铺装修的公司网站,网站建设技术 论坛❤️前言 大家好#xff01;今天这篇博客和大家聊一聊关于Linux下的基础IO。 正文 在阅读本篇博客之前#xff0c;请大家先回顾一下C语言文件操作的一些方法#xff0c;这里可以看看我之前记录的一些内容#xff1a; 【C语言】C语言成长之路之文件操作_MO_lion的博客-CSD…❤️前言 大家好今天这篇博客和大家聊一聊关于Linux下的基础IO。 正文 在阅读本篇博客之前请大家先回顾一下C语言文件操作的一些方法这里可以看看我之前记录的一些内容 【C语言】C语言成长之路之文件操作_MO_lion的博客-CSDN博客https://blog.csdn.net/MO_lion/article/details/128730282?spm1001.2014.3001.5501 除此以外我们要引入C语言默认会打开的三个输入输出流它们分别是stdin、stdout、stderr它们三个是FIFE*类型的文件指针。         我们知道在Linux系统下一切事物都可以视作文件进行处理那么键盘和显示屏也可以看做是两个文件大家可以猜猜为什么C语言要默认打开文件指针呢其实就是因为这三个文件指针指向的就是输入输出设备文件这样我们便可以对键盘和显示屏进行读写举例来说我们用printf和scanf就是用到这些文件指针对设备文件进行写入和读取。 系统级IO 要操作文件我们不仅仅可以使用语言带有的文件接口也可以使用操作系统提供的系统调用接口。 系统调用接口 可能你会对系统调用接口感到疑惑它是什么呢让我们来看下面这张图 通过上面的这张图片我们可以看出系统调用接口与库函数的关系我们可以认为C语言中的文件操作函数都是对系统调用的封装其目的是让我们用户更规范安全的操作文件。         系统调用的意义与上述的封装的意义很相似。操作系统在管理资源的时候并不相信任何用户的操作它采取的是一刀切的方式来减少可能发生的危险操作不让用户直接操作底层数据但是又要让用户进行上层的操作于是操作系统便在用户和底层数据之间加上了一层系统调用接口。系统调用接口的存在能很好地规范用户的操作保护底层的数据。 接着我们用系统调用接口演示一遍简单的文件读写操作 写文件 // 简单的写文件 #include stdio.h #include string.h #include unistd.h #include sys/types.h #include sys/stat.h #include fcntl.hint main() {umask(0); // 将权限掩码设置为0// file descriptor: 文件描述符int fd open(lion, O_CREAT|O_WRONLY, 0666); if(fd 0){perror(open);return -1;}const char* message I like Linux!\n;write(fd, message, strlen(message));close(fd);return 0; } 上述程序成功的创建出一个文件并向其中写入了一段字符 读文件 // 读文件 #include stdio.h #include string.h #include unistd.h #include sys/types.h #include sys/stat.h #include fcntl.hint main() {// file descriptor: 文件描述符int fd open(lion, O_RDONLY); if(fd 0){perror(open);return -1;}char buf[1024] {0};read(fd, buf, 1023);printf(%s, buf);close(fd);return 0; }运行结果 现在我们根据上面的程序对文件读写的系统调用接口进行介绍 打开文件open 用man指令看看open的文档 #include sys/types.h #include sys/stat.h #include fcntl.h int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode); pathname: 要打开或创建的目标文件 flags: 打开文件时可以传入多个参数选项用下面的一个或者多个常量进行“或”运算构成flags。 mode:创建文件时该文件的权限参数。 参数:         O_RDONLY: 只读打开         O_WRONLY: 只写打开         O_RDWR : 读写打开         这三个常量必须指定一个且只能指定一个         O_CREAT : 若文件不存在则创建它。需要使用mode选项来指明新文件的访问权限         O_APPEND: 追加写 返回值         成功新打开的文件描述符         失败-1 文件描述符 在继续了解其他系统调用之前我们先来聊聊open正常返回的返回值文件描述符(file descriptor)。 文件描述符fd是一个int类型的整数顾名思义它在每个系统调用接口的使用中扮演代表某个文件的角色就类似于C语言中的FIFE*指针。那么这样简单的int类型整数是如何做到代表一个文件的呢 我们可以打印出fd的值会发现它们的值都是一些接近0的小整数。这些值的意义是什么呢 这里我们又要引出一个新的知识当每个进程要对某些文件做管理时会有一个文件描述符表对所有的文件结构进行对应映射也就是说通过这个文件描述符表就可以让进程找到对应的文件并操作它。文件描述符表的映射是借由什么完成的呢其实就是依靠数组下标这里的数组下标指的就是文件描述符了。         具体的内核存储结构是这样的当我们打开文件时操作系统在内存中要创建相应的数据结构来描述目标文件于是就有了file结构体表示一个已经打开的文件对象。而进程执行open系统调用所以必须让进程和文件关联起来。每个进程控制块task_struct都有一个指针*files, 指向一张表files_struct,该表最重要的部分就是包涵一个指针数组每个元素都是一个指向打开文件的指针所以本质上文件描述符就是该数组的下标。所以只要拿着文件描述符就可以找到对应的文件。我们可以参照下图进行想象 其他常用的IO系统调用接口 除了上面给出的系统调用接口的简单信息大家也可以通过man指令的2号选项进行系统调用接口的文档信息查找。 系统默认打开的文件描述符 当进程要对文件进行操作时就需要使用文件描述符因为所有IO库函数的底层都是封装了系统调用的使用系统调用就需要传入文件描述符。而我们又知道Linux下一切事物都可以看做文件也就是说键盘和显示器也要看做文件那么当我们在进行对键盘和显示器文件的输入输出时也就需要文件描述符但是在平时对键盘和显示屏做输入输出时我们其实并没有手动的创建过文件描述符那么这些用于操作IO设备的文件描述符是从哪里来的呢 其实当我们创建一个进程以后操作系统会默认帮我们打开三个文件描述符分别占用文件描述符表的前三个位置代表下标0、1、2(这三个数字也对应C语言中打开的三个标准输入输出的FIFE*指针stdin、stdout、stderr)这三个文件描述符分别代表的是标准输入、标准输出、标准错误输出它们一般也对应着这三个物理设备键盘、显示器、显示器。 其实这里我们也可以验证上层语言的库函数与系统操作的一些关系如果我们访问C语言默认打开的三个文件指针 printf(stdin-fd: %d\n, stdin-_fileno); printf(stdout-fd: %d\n, stdout-_fileno); printf(stderr-fd: %d\n, stderr-_fileno);  我们就会发现对应的输出结果是        输出结果表明系统和C语言默认打开的东西产生了关联这与我们之前所说库函数是由系统调用封装而成的观点不谋而合。 当我们掌握了这样的信息那我们也就可以自己使用系统调用接口进行键盘读入和显示屏输出。我们可以运行一下以下的代码 #include stdio.h #include string.h #include unistd.h #include sys/types.h #include sys/stat.h #include fcntl.hint main() {// file descriptor: 文件描述符int fd open(lion, O_RDONLY, 0666); if(fd 0){perror(open);return -1;}//之前所输入的信息//const char* message I like Linux!\n;// 用户级缓冲区char buf[1024] {0};read(fd, buf, 1023);// 我们可以看看这两个操作的效果write(1, buf, strlen(buf));printf(%s, buf);close(fd);return 0; } 运行结果如下   大家也可以使用read来读取0号文件(键盘)的信息这里就不再演示。 文件描述符的分配规则 我们现在了解了一些文件描述符的概念和使用方式那么当我们在一个进程中打开一个新出现的文件这个文件的文件描述符是如何分配的呢 我们直接使用代码进行实验 #include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.hint main() {int fd open(myfile, O_RDONLY);if(fd 0){perror(open);return 1;}printf(fd: %d\n, fd);close(fd);return 0; } 运行结果是得到了一个值为3的文件描述符先前说过系统默认缺省的占用了0、1、2三个文件描述符这里得到的值为3我们可以合理的猜测fd是直接按照表的顺序从上往下给的值。那么当我们再关闭了之前的文件继续试着打开新的文件 #include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.hint main() {close(0);//close(2);int fd open(myfile, O_RDONLY);if(fd 0){perror(open);return 1;}printf(fd: %d\n, fd);close(fd);return 0; } 结果是fd:0。也就是说当我们一开始就将对应键盘的文件描述符0给关闭掉新打开的文件就直接占据了原来的0的位置。那么现在我们就可以得出结论文件描述符的分配规则就是在files_struct数组当中找到当前没有被使用的最小的一个下标作为新的文件描述符。 那么现在我们可以完善一下上面的进程控制文件的图片 重定向 按照之前的知识当我们让一个新文件占据显示器的文件描述符这时候所有原本写入显示器的信息将会被写入至这个新的文件中让我们运行代码检验一下这样的现象 //一段伪代码:// 关闭显示器文件打开新的文件 close(1); int fd open(lion, O_WRONLY|O_CREAT, 00644);if(fd 0){perror(open);return 1; }printf(fd: %d\n, fd); fflush(stdout);close(fd);运行结果如下 我们将本应该输入到屏幕上的信息输入到了文件lion中这种现象就叫做输出重定向不知道大家是否知道命令行代码中的重定向指令其实重定向指令就是在进程运行时将对于IO设备的输入输出改成对于某个其他文件的输入输出。 我们将上述过程以图片形式展现如下图所示 除此之外让我们重新简单了解一下命令行指令中的一些重定向这里参考chatgpt的回答 除了上面的“通过关闭显示器文件然后用新的文件来占用显示器文件的文件fd1”所产生的输出重定向以外我们其实主要通过别的方式来完成重定向的动作这需要一些系统调用接口来完成它们分别是 open()用于打开文件。在重定向中open() 被用于打开指定的文件并返回一个文件描述符。close()用于关闭文件。在重定向中close() 被用于关闭不再需要的文件描述符。dup()和 dup2()用于复制文件描述符。在重定向中dup() 可以用来复制文件描述符使得多个文件描述符指向同一个文件。dup2() 则可以用于将一个文件描述符复制到另一个特定的文件描述符从而实现重定向。其中比较常用的是dup2我们主要了解的就是它。 使用 dup2 系统调用 在继续了解重定向中的系统调用的运作方式之前我们首先来简单的看看dup2的文档解释。 简单来说我们可以向dup2中输入两个文件描述符 oldfd 和 newfd dup2会将newfd代表的文件改变成oldfd所代表的文件也就是说当我们使用了dup2以后这两个文件描述符将会同时代表原来oldfd所描述的文件。从文件描述符作为数组下标的概念上来说就是下标本身的值不变而将下标对应的值都改为oldfd所指向的元素值。 举例图如下 输出重定向 (, ) 使用 open() 打开指定文件获得一个文件描述符。使用 dup2() 将标准输出的文件描述符1复制到新打开的文件描述符上使得标准输出被定向到文件。 输入重定向 () 使用 open() 打开指定文件获得一个文件描述符。使用 dup2() 将标准输入的文件描述符0复制到新打开的文件描述符上使得标准输入被定向到文件。 错误输出重定向 (2, 2) 类似于输出重定向但是文件描述符是标准错误输出的2。 将标准错误和标准输出合并 (21) 使用 dup2() 将标准错误输出的文件描述符2复制到标准输出的文件描述符上使得标准错误和标准输出指向同一个位置。 这些操作的组合和顺序使得在Linux系统中能够对输入输出进行高度的控制从而实现重定向的功能。这是Linux操作系统中强大而灵活的特性之一。 加深对“一切皆文件”的理解 我们曾经提出过“Linux下一切皆文件”的观点那么在这篇关于系统IO的博客中这个观点又可以如何进行重申呢 今天我们通过对于进程的文件管理进行对“一切皆文件”进行重新审视我们知道进程可以通过文件描述符fd对文件进行访问和操作那么便可以以此入手 通过上图我们可以看见在虚拟文件系统VFS(vitrual file system)对各种不同事物、外部设备的统一描述下所谓“一切皆文件”的大致实现方式。从这以后我们对于“一切皆文件”的理解不再只局限于此结论的应用方面还有底层实现机制方面的理解。 研究语言层IO 用户缓冲区的概念与深刻理解 通过上面的学习我们对底层的系统调用有了一定的认识现在重新返回到对于应用层设计的一些研究认识。 让我们先来看下面的一段代码 const char* fstr hello fwrite!\n; const char* str hello write!\n;printf(hello printf!\n); fprintf(stdout,hello printf!\n); fwrite(fstr,strlen(fstr),1,stdout);write(1,str, strlen(str));这段代码中调用了三个C语言库中的输出函数和一个系统调用接口write并将一些字符输入到了屏幕上面我们将其运行起来 结果不出所料毕竟从刚刚学习编程的时候开始我们就知道程序中的语句按照从上到下的顺序执行。那么我们现在想要将这里的输出全部都重定向到一个文件中 这是怎么回事为什么程序的最后一个输出语句反而第一个写入到了文件中呢我想大家的脑海中应该会冒出这样的问题那么我们现在就正式引入用户缓冲区的知识。 当我们使用C语言提供的输出函数向一些文件进行输出打印时其实字符串首先并不是直接被输出到了对应的文件中而是暂时被存在了一个C语言为我们提供的缓冲区中这个缓冲区有两种缓冲方式分别是行缓冲和全缓冲。(除此之外系统调用接口write不受C语言的管束只要使用者规定了向什么文件中写入我们可以看做它会直接向其中进行写入操作。)         行缓冲我们曾经在编写进度条程序的时候遇到过它的意思是缓冲区会一直不刷新直到有换行符被写入到缓冲区中缓冲区才会被刷新。我们知道缓冲区对于显示器文件的刷新方式就是行缓冲而当时我们编写进度条的时候并不想换行于是采用了fflush函数直接刷新缓冲区中的数据至显示器文件中。         全缓冲是缓冲区对于除了显示器文件以外的其他普通文件的刷新方式这种方式是只有当缓冲区被写满时才会进行刷新。         除此之外缓冲区的刷新的本质可以看做调用了系统调用接口write将缓冲区的数据直接写入到某个文件中。从中我们可以看出缓冲区的设计就是一种对于系统调用的封装和规范。 引入缓冲区的知识以后让我们将目光重新放回到上面的两种不同输出情况我们大致可以猜出造成运行结果不同的原因跟写入文件的不同缓冲方式有关。 第一次操作中由于我们直接向显示器中打印信息缓冲区刷新模式是行缓冲于是所有的输出语句都是当被写入到缓冲区之后就直接刷新到了显示器上。而第二次操作进行了输出重定向将对显示器文件的输出重定向为向普通文件的输出于是缓冲区的刷新方式便由行缓冲改变成了全缓冲那么你肯定就有这样的疑问了难道是这三条字符串将缓冲区给写满了吗答案并不是这样毕竟如果是这样也不会造成这两种结果输出顺序上的不一致。那么这三条字符串是怎么被刷新到屏幕上的呢让我们继续对此进行研究。 我们在原有代码的基础上加上一个fork函数创建出一个子进程 const char* fstr hello fwrite!\n; const char* str hello write!\n;printf(hello printf!\n); fprintf(stdout,hello printf!\n); fwrite(fstr,strlen(fstr),1,stdout);write(1,str, strlen(str)); fork(); 并对这段程序进行上面两种情况的输出 我们发现第二种情况非常特殊不仅C接口的输出在write之后其中的字符串还被打印了两遍。对比这两段代码我们可以猜测这里的不同一定与子进程中的某个动作有关多出的三行打印应该就是子进程造成的。而我们看到fork以后我们并没有主观上的对其做任何的操作那么子进程之后还做了什么样的动作呢很显然子进程最后直接退出了毕竟这时除了退出已经没有任何的动作。 现在便揭晓特殊情况的原因那就是除了缓冲区本身的刷新规则以外当一个进程退出时缓冲区也会进行一次刷新。(这里具体的实现可以看做C语言进程调用了退出函数exit()而exit()由单纯执行结束进程功能的系统调用_exit()和刷新缓冲区的函数fflush()组合而成) 这样我们便可以分析上面种种情况的成因我们将四个输出分别编号为1~4。2号输出的成因首先直接执行write的输出然后当进程退出时缓冲区刷新由于全缓冲而暂时存在于缓冲区的数据最后被刷新到了屏幕上。4号成因除二号相同的过程以外子进程会复制一份于父进程相同的缓冲区然后当最后退出时刷新到显示器上。 至此上面的四种情况以及C语言提供的缓冲区规则已经基本分析完毕。缓冲区的规则我们大致清楚了现在来看看它本身的一些性质。 1.为什么要有缓冲区呢第一个是缓冲区可以提高用户层输出的效率。当我们直接使用系统调用将数据传输到外设上时对比在内存中的读取是比较慢的那么我们如果多次直接调用系统调用来进行输出就会造成很多的资源浪费这就像是山上的蓄水池和山脚下的溪流一样我们将许多将要输出的数据存起来一次性进行输出会提高输出效率。         第二个是可以配合格式化什么是格式化呢我们使用C语言printf时肯定听说过格式化输出格式化操作也就是将本身没有特殊意义的各种字符赋予不同的意义、进行不同的处理比如字符串输出我们就以\0作为输出的结尾。打比方说我们输出一个数字就要用%d来确定它是以整数形式进行输出的但如果我们都直接使用系统调用接口进行输出那也就没有什么类型差异了输出的都是字符这不利于我们对于数据的处理。         2.缓冲区存在于哪里缓冲区本质上的作用是C语言设计出来要对文件的输入输出做缓冲那么它就不可避免的与C语言的文件结构体FIFE扯上关系。事实上一个FIFE对应的文件的缓冲区的相关字段和维护信息就是被存储在FIFE本身中。FIFE本身就是需要占用一段空间的当我们调用fopen打开一个文件的过程就是在语言层为我们malloc出一个空间用于存放FIFE对象并初始化对应的信息(文件fd、缓冲区字段等)。         3.缓冲区属于用户本身不属于操作系统。在语言层面上的所有东西都是属于用户的缓冲区是属于用户FIFE对象也是属于用户的。 结语 今天的博客就分享到这谢谢大家
http://www.zqtcl.cn/news/451995/

相关文章:

  • 学校多语言网站建设网络维护网站建设培训
  • Wordpress外贸网站搭建公司建站系统的应用场景
  • 网站推广网络推广方wordpress汉语公益
  • 长沙做网站的公司有哪些宁波奉化建设局网站
  • 温岭专业自适应网站建设承德招聘信息网
  • 做公司网站的模板下载wordpress e
  • 网站建设基本知识wordpress 没有小工具
  • 北京完美建设有限公司网站酒店加盟
  • 山东网络推广网站德州市建设局质监站网站
  • api模式网站开发网站打开后显示建设中
  • 排名好的郑州网站建设免费营销培训
  • 美橙互联网站网站主要应用
  • 淘宝客网站做appuv推广平台
  • 网站公司可以做英文网吗图片加字制作免费
  • 海口个人建站模板精品课程云网站建设
  • 阿里网站空间莱芜新闻视频回放
  • 高清网站建设的好处wordpress 房产模板
  • 在建工程查询网站怎么自己开发网站
  • 旧电脑怎么做网站如何自己弄个免费网站
  • 聊城网站营销WordPress工作发布
  • 建造网站需要什么汽车网站建设
  • 网站建设app郑州发布评论
  • 福州网站制作建设网页设计图片是怎么显示的
  • 天津通用网站建设收费网站建设怎么在png上写文字
  • 浏阳做网站报价高校网站站群建设公司
  • 海口网站提升排名网站建设与管理考试题
  • 做网站的算什么行业ui视觉设计常用软件是什么
  • 成都网站建设公司哪家好西安搬家公司哪家便宜
  • 程序员自己做网站怎么能来钱上海猎头公司哪家好
  • 无忧网站建设哪家好手机网站php开发