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

酒店招聘做的好的网站如何开网店要多少钱

酒店招聘做的好的网站,如何开网店要多少钱,网站建设工具的公司,如何登入 WORDPRESS 后台IO 概念引入位图的概念IO的系统调用函数openwriteread()close简单使用样例#xff1a; 文件描述符fd默认文件流stdin/stdout/stderr文件描述符的分配规则 重定向的概念输出重定向输入重定向追加重定向dup2()系统调用总结 文件缓冲区深入理解缓冲区的概念输出缓冲区部分代码解释… IO 概念引入位图的概念IO的系统调用函数openwriteread()close简单使用样例 文件描述符fd默认文件流stdin/stdout/stderr文件描述符的分配规则 重定向的概念输出重定向输入重定向追加重定向dup2()系统调用总结 文件缓冲区深入理解缓冲区的概念输出缓冲区部分代码解释总结 stdout和stderr的区别总结自己实现一个perror 文件系统inode发现系统还有空间为什么不能创建文件 软硬链接 概念引入 在学习C语言的时候我们学过一些文件操作的函数比如fopen,fgets,fputs,fclose等等其实这些函数的功能就是在操作文件进行IO读取工作。这些是C语言封装的函数。 然而C语言封装的函数里面一定有OS层面的动作因为IO设计到硬件操作而对于硬件的操作一定要通过系统调用让OS帮助我们完成IO操作。 所以为了更好的让大家理解IO原理先介绍一下IO的系统调用接口。 位图的概念 在介绍系统调用函数之前需要了解一下位图的概念。顾名思义就是每个比特位都有不通过的含义代表着不同的功能。 下面使用一个例子介绍位图的应用 1 #includestdio.h2 3 4 // 用int中的不重复的一个bit就可以标识一种状态5 // 第1个比特位表示功能一第二个比特位表示功能二第三个比特位表示功能三6 #define ONE 0x1 //0000 00017 #define TWO 0x2 //0000 00108 #define THREE 0x4 //0000 01009 10 11 void show(int flags)12 {13 //哪个标志的比特位是1就完成对应的功能14 if(flags ONE) printf(功能ONE\n);15 if(flags TWO) printf(功能TWO\n);16 if(flags THREE) printf(功能THREE\n);17 }18 19 int main()20 {21 show(ONE); //选择功能122 show(TWO); //选择功能223 show(ONE | TWO); //选择功能1和224 show(ONE | TWO | THREE); //选择功能123 25 return 0;26 } 从上面的运行结果可以来看我们使用位图的概念实现了的方法可以选择任意功能。 IO的系统调用函数 open 类比fopen的使用使用man 2 open查询open函数的用法。我们使用时经常使用带mode的函数。 第一个参数文件路径 第二个参数flags功能位位图的概念 第三个参数权限可以使用16进制来表示一般使用0x666表示rw权限。 返回值成功时返回新打开的文件描述符。失败时返回-1. flags打开文件时可以传入多个参数选项用下面的一个或多个常量进行或运算构成flags。 O_RDONLY:只读打开O_WRONLY只写打开O_RDWR读、写打开 上面这三个常量必须写一个且只能写一个O_CREAT若文件不存在则创建它。需要使用mode选项来指明文件的访问权限。O_APPEND追加写。 下面我们简单举个例子来打开文件 1 #includestdio.h2 #includesys/types.h3 #includesys/stat.h4 #includefcntl.h5 6 int main()7 {8 //只读并且没有文件创建。9 int fd open(log.txt, O_WRONLY|O_CREAT, 0666);// rw-rw-rw 10 if(fd 0)11 {12 perror(open:);13 return 1;14 }15 16 printf(打开成功, fd %d \n, fd);17 18 return 0;19 } write 类比fwrite的使用使用man 2 write查询open函数的用法。 fd文件描述符 buf要写的字符串。 count要写的大小单位是字节 返回值ssize_t 实际写的有效字节数。 read() 类比fread。 将fd的功能读到字符串buf中读取count个字节。 close 关闭指定文件通过文件描述符关闭。 返回值0代表成功。-1代表失败。 简单使用样例 创建一个log.txt文件并且追加输入111222333 1 #includestdio.h2 #includestring.h3 #includestdlib.h4 #includeunistd.h5 #includesys/types.h6 #includesys/stat.h7 #includefcntl.h8 9 int main()10 {11 //只读并且没有文件创建追加写入12 int fd open(log.txt, O_WRONLY | O_CREAT | O_APPEND, 0666);// rw-rw-rw13 if(fd 0)14 {15 perror(open:);16 return 1;17 }18 19 printf(打开成功, fd %d \n, fd);20 const char* s1 111111111111;21 const char* s2 222222222222;22 const char* s3 3333333333333;23 write(fd, s1, strlen(s1));24 write(fd, s2, strlen(s1));25 write(fd, s3, strlen(s1));26 27 close(fd); 28 29 return 0;30 } 文件描述符fd 通过open系统调用函数的理解发现文件描述符其实就是一个小整数并且一直是3为什么呢 这就要引入stdinstdoutstderr的概念。 默认文件流stdin/stdout/stderr 在我们操作系统启动的时候默认会打开三个流他们就是stdinstdoutstderr即标准输入流、标准输出流、标准错误流。对应的硬件分别是键盘让我们能输入、显示器让我们能看见、显示器出错了也能看见。 看下面一段程序 1 #includestdio.h4 int main ()5 {6 7 printf(stdin: %d\n,stdin-_fileno);8 printf(stdout: %d\n,stdout-_fileno);9 printf(stderr: %d\n,stderr-_fileno);10 return 0; 11 }12 我们可以猜测012是被这默认打开的三个流占用了所以我们每次再打开文件的时候被分配的就是从3开始了。 并且在man手册查看一下他们的介绍发现都是FILE* 类型的。 因此我们猜测FILE是一个结构体并且结构体的内部一定有fd。当然这个结构体一定是由C语言提供的。 而我们上面学习了系统调用函数使用的是fd操纵的文件我们可以推测C语言的文件操作一定封装了系统调用的接口并且通过struct FILE里面的fd来和系统沟通因为系统只认识fd不认识FILE*。 下面我将fd与文件的关系可视化出来帮助大家理解 解释通过进程的pcb里面可以找到一个数组其中fd就是数组的下标数组内容存着文件的属性信息。因此当我们打开一个文件的时候OS会在数组中申请一个最小的下标通常情况下最小为3然后内容存上结构体的地址这样我们就能通过fd操作文件啦。 现在我们知道文件描述符就是从0开始的小整数。当我们打开文件时操作系统在内存中要创建相应的数据结构来描述文件。于是就有了file结构体。表示一个已经打开的文件对象。而进程执行open系统调用所以必须让进程和文件关联起来。每个进程都有一个指针*file指向一张表files_struct该表最重要的部分就是包含一个指针数组每个元素都是一个指向打开文件的指针所以本质上文件描述符fd就是该数组的下标。所以只要拿着文件描述符就可以找到对应的文件。 文件描述符的分配规则 现在我们已经理清楚文件描述符是什么有什么用。那么他的分配规则是什么呢fd分配最小下标分配原则。 关闭0号文件那么我们如果打开文件的话描述符就为0如下 1 #includestdio.h2 #includestring.h3 #includestdlib.h4 #includeunistd.h5 #includesys/types.h6 #includesys/stat.h7 #includefcntl.h8 9 int main()10 {12 close(0); //关闭0号文件描述符 13 int fd open(log.txt, O_WRONLY | O_CREAT | O_APPEND, 0666);// rw-rw-rw14 if(fd 0)15 {16 perror(open:);17 return 1;18 }19 20 printf(打开成功, fd %d \n, fd);28 close(fd);30 return 0;31 }可以验证OS总是优先分配最小的数组下标即便是0、1、2号下标也不例外 重定向的概念 输出重定向 看一下下面的代码 1 #includestdio.h2 #includestring.h3 #includeunistd.h4 #includesys/types.h5 #includesys/stat.h6 #includefcntl.h7 8 int main ()9 {10 11 close(1);12 int fd open(log.txt, O_WRONLY | O_CREAT | O_TRUNC, 0666); //fd的文件描述符为113 //下面的内容本应该打印到屏幕上。但实际上却没有打印出来。14 printf(打开文件分配的fd为%d\n, fd); 15 printf(打印到屏幕上的内容\n);16 fprintf(stdout, hello fprintf\n);17 const char* s1 hello fwrite\n;18 fwrite(s1, 1, strlen(s1), stdout);19 22 fflush(stdout);23 close(fd);24 return 0;25 }运行结果本应该显示在屏幕上的内容却被输出到了文件里这个现象叫做输出重定向但是为什么呢 下面我将用图例解释一下产生上面情况的原因 注意stdin,stdout,stderr在C语言是宏定义分别被定义成为了0、1、2。在代码中我们首先关闭了1号文件描述符然后又打开了文件显然log.txt文件的文件描述符就是1也就是说1号下标的内容由标准输出屏幕变成了指向log.txt的指针。所以我们在代码中对stdout文件输出内容在语言层面其实就是对1号文件描述符输出内容然而语言层面不知道这个改变因为文件描述符是OS分配的所以就造成了输出重定向。 输入重定向 理解输出重定向例子后我们很容易就能写出输入重定向。 8 int main ()9 {10 11 // 关闭stdin12 close(0);13 int fd open(log.txt, O_RDONLY);14 if(fd0)15 {16 perror(open:);17 return 1;18 } 19 printf(fd %d \n, fd);20 char buffer[128];21 fgets(buffer, sizeof buffer, stdin);22 printf(buffer:%s\n, buffer);23 close(fd);}运行结果 可知我们本该需要使用键盘输入的时候但是却不需要我们输入而是从我们打开的文件中读取了一行。这就完成了输入重定向工作。 追加重定向 我们实现一直往log.txt追加输出内容的代码 1 #includestdio.h2 #includestring.h3 #includeunistd.h4 #includesys/types.h5 #includesys/stat.h6 #includefcntl.h7 8 int main ()9 {10 11 close(1);//将文件打开方式变为追加打开即可12 int fd open(log.txt, O_WRONLY | O_CREAT | O_APPEND, 0666); //fd的文件描述符为113 //下面的内容本应该打印到屏幕上。但实际上却没有打印出来。14 printf(打开文件分配的fd为%d\n, fd); 15 printf(打印到屏幕上的内容\n);16 fprintf(stdout, hello fprintf\n);17 const char* s1 hello fwrite\n;18 fwrite(s1, 1, strlen(s1), stdout);19 22 fflush(stdout);23 close(fd);24 return 0;25 }运行程序前后log.txt内容确实被追加了 dup2()系统调用 上面的例子只是让我们见识一下重定向是什么样子。而实际工程中我们多使用dup2()系统调用来完成此功能。 把oldfd文件描述符的内容给nwefd相当于修改的是数组内容。 看下面代码示例 8 int main (int argc, char* argv[])9 {10 if(argc!2)11 {12 return 1;13 }14 15 int fd open(log.txt, O_CREAT| O_WRONLY|O_TRUNC, 0666);16 printf(fd:%d\n, fd);17 dup2(fd,1); //将stdout的内容修改为fd18 printf(打印屏幕上的内容%s\n,argv[1]);19 20 close(fd);21 return 0; } 运行结果 通过上面的例子我们使用dup2完成了输出重定向 总结 重定向的本质其实是在OS内部更改fd对应的内容指向 重定向很容易解决Linux系统一切皆文件的设计理念。它把显示器、键盘、磁盘当成文件全部封装成struct file在用户看来只需要操作对应的结构体即可完成重定向的工作。用户根本不需要知道硬件的细节。也恰好能体现封装的思想。 文件缓冲区 什么是缓冲区 缓冲区就是一段内存区域介于CPU和硬盘之间因为要执行IO的话CPU肯定会访问硬盘。CPU的速度是ns级别硬盘的速度是ms级别。如果让CPU直接访问的话肯定会拖慢系统的速度。因此我们可以在内存中开辟一小段区域这段区域就叫做缓冲区。 缓冲区有什么用 缓冲区可以提高效率。 写透模式wrrite throughCPU直接向硬盘写入耽误CPU时间慢。 写回模式write backCPU将数据写到缓冲区后就干别的事情去了让缓冲区自己往硬盘写入写完报告给CPU即可。(不耽误CPU时间快也可以提高用户的相应速度)。 缓冲区的刷新策略 立即刷新写完就立马刷新、行刷新/行缓冲遇到\n就立马刷新)、满刷新/全缓冲写满缓冲区才刷新。 一般而言行缓冲的设备文件显示器全缓冲的设备磁盘文件 深入理解缓冲区的概念 下面我们先看一段代码 8 int main ()9 {10 11 //C语言提供的12 printf(hello world\n);13 const char* s1 hello frite\n;14 fwrite(s1, 1, strlen(s1), stdout);15 fprintf(stdout,hello fprintf\n);16 17 //OS系统提供的接口18 const char *s2 hello write\n;19 write(1, s2, strlen(s2));20 21 22 fork(); 23 return 0;24 } 程序运行结果如下 **观察发现程序运行时是正常的但是当我们重定向到文件里面后发现C语言提供的函数打印了两次而系统调用函数只打印一次。**如果我们把fork去掉之后程序正常运行。我们猜想这种情况一定和fork有某种关系。 解释 如果向显示器打印刷新策略是行刷新那么最后执行fork的时候一定是函数执行完了同时数据已经被刷新了此时再fork就没有意义了。如果对应的程序进行了重定向要向磁盘文件打印隐形的刷新策略变成了全缓冲(\n便不管用了)fork的时候一定是函数已经执行完了但是数据还没有刷新因为刷新会清空缓冲区这涉及到写时拷贝当父进程结束运行会刷新缓冲区同时触发写时拷贝赋值给子进程子进程退出时再刷新一份这样就相当于打印了两次。为什么系统调用函数只打印一次呢 原因是我们上面提到的缓冲区其实是C语言层面上的调用C函数时会将数据写到C提供的缓冲区上。而fork后出发写时拷贝时父进程刷新数据到OS缓冲区1份子进程刷新到OS缓冲区2份因此C语言层面上会打印两次。而write系统调用会直接将数据写到OS缓冲区因为他是系统提供的函数不属于C语言函数因此不涉及C语言层面上的写时拷贝动作因此只会刷新一次。 下图解释了这种现象 输出缓冲区部分代码解释 我们在输出缓冲区当时红色框框的代码没有讲解现在我们可以解释一下 当我们关闭了1号文件打开了log.txt此时log.txt的文件描述符为1.刷新策略由行刷新变成了普通刷新因为是往文件里打印因此我们输出的数据其实是在stdout的缓冲区里并没有刷新呢如果我们提前关闭close1,因为数据还在缓冲区里还没有来得及刷新到文件里。所以log.txt文件里什么都没有。当我们提前fflush文件的时候已经把数据刷新到文件里因此再关闭文件就没事了。 总结 所有的设备按道理来说都倾向于全缓冲缓冲区满了才刷新这样能进行更少的IO操作提高效率。因为和外设IO时数据量的大小不是主要矛盾和外设预IO的过程准备过程是最耗费时间的。 为了照顾到用户体验显示器一般都是行刷新。极端情况下我们也可以自定义刷新规则。 **C语言的缓冲区在哪里呢**和fd一样存在FILE结构体里面包含了该文件fd对应的语言层的缓冲区结构。 stdout和stderr的区别 stdout和stderr所对应的硬件都是显示器但是他们具体有什么区别呢 名字上stdout叫标准输出流stderr叫标准错误流。 让我们看下面一段代码 该程序输出的1表示使用stdout打印的。输出2表示使用stderr打印的。 1 #includeiostream2 #includestdio.h3 4 int main()5 {6 //stdout - 17 printf(hello printf 1\n);8 fprintf(stdout, hello fprintf1\n);9 10 //stderr11 perror(hello perror 2);12 13 // cout - 114 std::cout hello cout 1std::endl;15 //cerr - 2 16 std::cerrhello cerr 2std::endl;17 18 return 0;19 } 程序首先都被打印到了屏幕上证明他们对应的硬件都是显示器。 我们在此程序的基础上运行下面的命令 重定向后发现stderr的输出仍然打印出来了但是stdout的输出被重定向到log.txt。 结论因为屏幕只有一个stdin和stdout都打开了显示器文件即一个显示器文件被打开了两次有两个文件描述符输出重定向只是重定向了fd1描述符并没有影响到stderr。因此stderr仍然打印到屏幕上。 应用 //运行下面的命令即可把两种输出分别重定向到两个文件里。./myfile log.txt 2err.txt//运行下面的命令即可把两种输出重定向到一个文件里。./myfile log.txt 21总结 一般而言程序如果可能出问题的话使用stderr或者cerr来打印。 如果是常规文本的打印建议使用cout或者stdout打印。 自己实现一个perror 在我们的文件操作函数出错之后出错信息一般都会存在一个全局变量errno里面我们一般都使用perror函数来打印错误信息但是该接口不需要errno。说明该接口一定封装了errno。代码如下 5 void myperror(const char* s)6 {7 //使用errno全局变量打印错误8 fprintf(stderr, %s %s\n,s, strerror(errno));9 } 文件系统 文件系统顾名思义是管理文件的系统。如下图是Linux ext2文件系统的磁盘文件系统图。 磁盘是典型的块设备硬盘分区被划分为一个个的block。一个block的大小是格式化的时候确定的并且不能更改。其中启动块Boot Block的大小是确定的。 Block Group块组文件系统会根据分区的大小划分为好多个Block Group。而每个Block Group有着相同的结构。超级块Super Block存放整个文件系统本身的结构信息。记录的主要信息有block和inode的总量未使用的block和inode的数量一个block和inode的大小最近一次挂载的时间最近一次写入数据的时间最近一次检查磁盘的时间等其他文件系统的相关信息。Super Block如果被损坏整个文件系统就被破坏了。因此有好多个Block Group都有Super Block。GDTGroup Descriptor Table块组描述符描述块组的属性信息这个块组多大已经使用了多少有多少inode已经占用了多少还剩多少一共有多少个block使用了多少。块位图Block Bitmap位图中记录着哪个数据块已经被占用哪个数据块没有被占用。inode位图inode Bitmap每个bit表示一个inode是否空闲可用。inode Tablei结点表存放文件属性和文件大小所有者最近修改时间等。Data blocks数据区存放文件内容。 众所周知文件 属性 数据因此flie inode Table Data blocks inode inode是一个结构体存放着文件的各种属性。 struct inode {//文件大小//文件的inode编号//其他属性int blocks[15] //(0-11是直接索引12-15是间接索引) }inode与文件名的关系我们使用文件名去寻找文件但是linux其实并不认识文件名它只认识inode号因此在每个目录下面文件名inode都有着对映的键值对可以帮助转化成inode。目录也是文件也有ionde号也有data Block。 因此对于一个目录进入目录需要X执行权限创建文件需要W写权限要写数据块显示文件名与属性r读权限要读数据块。 创建文件过程首先os申请一个inode号并且为之分配一个数据块然后更新inode表。完成之后更新目录的data block。 发现系统还有空间为什么不能创建文件 因为inode和data block是固定的。可能是没有ionde号了。 软硬链接 硬链接是通过inode引用另外一个文件引用计数1inode号相同相当于共享一个inode。软链接是通过名字引用另外一个文件引用计数不变新inode号相当于一个新的inode号指向老的inode号相当于快捷方式。
http://www.zqtcl.cn/news/487010/

相关文章:

  • 湖南门户网站设计公司免费自媒体网站
  • 美食网站建设项目预算域名解析站长工具
  • 网站如何备案工信局学网站开发首先学哪些基础
  • 什么网站利于优化河北省建设局网站材料备案
  • 自学装修设计从哪里入手沈阳百度seo
  • 做jsp网站用哪些软件下载如何利用网站赚钱
  • 注册网站域名需要什么湘潭公司做网站
  • 一个网站如何优化企业资质查询平台
  • 模板网站为什么做不了优化山西网络网站建设销售公司
  • 建设什么网站可以赚钱设计本网站是用什么做的
  • 荆州市网站建设策划师
  • 苏州中国建设银行招聘信息网站中国企业登记网
  • 网站服务器的重要性新闻软文范例大全
  • 茶叶网站建设一般的风格加大志愿服务网站建设
  • 湖州医院网站建设方案网页游戏知乎
  • 以网站建设为开题报告临海门户网站住房和城乡建设规划局
  • 河南省大型项目建设办公室网站wordpress置顶功能
  • 奉化网站建设三合一网站建设多少钱
  • wordpress文章页怎么调用网站图片wordpress菜单锚点定位
  • 网站建设运营合作合同网站建设英文合同
  • wordpress chrome插件开发图片式网站利于做优化吗
  • 如何做好品牌网站建设策划app要有网站做基础
  • 横沥网站建设公司wordpress运行php
  • 南皮网站建设价格网络推广这个工作好做吗
  • 长安大学门户网站是谁给做的网站排名logo怎么做
  • 襄樊做网站做网站做网站
  • 百度做网站续费费用网站开发的可行性
  • 电子商务网站建设效益分析如何才能做好品牌网站建设策划
  • 能打开各种网站的浏览器app文章目录wordpress
  • 网站注册页面html中国建设招标网网站