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

定制手机号码官方网站手工做衣服网站

定制手机号码官方网站,手工做衣服网站,义乌推广公司,怎么介绍自己做的电影网站吗目录 一、关于文件 1、文件类的系统接口 2、文件的含义 二、文件操作 1、C语言文件相关接口 2、系统接口 open close write read 三、文件描述符 关于fd fd的分配规则 输出重定向示例 输入重定向示例 追加重定向示例 dup2函数 缓冲区 stdout与stderr perror…目录 一、关于文件 1、文件类的系统接口 2、文件的含义 二、文件操作 1、C语言文件相关接口 2、系统接口 open close write read 三、文件描述符 关于fd fd的分配规则 输出重定向示例 输入重定向示例 追加重定向示例 dup2函数 缓冲区 stdout与stderr perror 一、关于文件 1、文件类的系统接口 首先不同语言都有不同的文件操作接口C语言、C、java都有各自的文件接口而这些文件接口的底层其实是封装的系统接口 之所以各个语言不直接使用文件类的系统接口是因为系统接口相比较各个语言封装出来的接口难度较大学习成本比较高各种语言对系统接口做封装是为了让接口更好的使用 其次也是为了跨平台这个特性如果每种语言对系统接口不封装直接调用系统接口那么所有的文件操作都必须使用操作系统接口无法在其他平台运行是不具备跨平台特性的 2、文件的含义 说起文件大部分人都想的是普通的磁盘文件例如记事本打开的文本文件、.exe之类的文件 其实站在系统的角度能够被input读取output写出的设备都叫做文件例如键盘、显示器、磁盘、网卡、显卡等外设都可以被称为文件 二、文件操作 1、C语言文件相关接口 我们先在Linux中写C语言中学习的文件接口 以w的方式打开如果文件不存在会创建一个新文件那么这个文件会创建在哪呢 很显然会创建在当前路径下而当前路径指一个进程运行起来的时候每个进程都会记录自己当前所处的工作路径而这个工作路径就是当前路径 上面的代码中test.txt这个文件是不存在的该路径下只有两个文件 所以在编译运行file.c后test.txt会在该路径下创建出来 由于当前进程的工作路径在这里所以创建出来的test.txt也就在这个路径下了 以w方式打开文件时不论文件里面是否有内容打开文件时做的第一件事就是清空文件内容哪怕我们什么都不干只是打开关闭文件文件内容都会被清空下面举个例子 我们向文件test.txt中写入hello 查看test.txt内容 这时改变file.c的内容将fprintf的相关代码删除 然后再编译运行myfile 发现test.txt里面的内容没有了大小为0 有了上面打开文件就会清空文件内容的基础再看下面的例子 先cat test.txt发现文件里没有内容 接着echo输出重定向的方式向test.txt写了一个字符串hellocat test.txt发现确实写入了 然后执行test.txt后再cat发现又被清空了 这里的符号可以当做一个命令表示要往文件里写入的而向文件写入首先做的就是打开这个文件上面也提到了打开文件做的第一件事就是清空文件内容所以我们就可以明白为什么执行完test.txt后test.txt中内容就被清空了 以上就是复习的C语言相关文件接口 2、系统接口 上面提到的C语言的库函数底层一定会调用系统调用接口 系统调用接口有open、close、write、read open 通过man了解一下open 有三个头文件需要包含然后看下面的两个open后面的参数 参数pathname代表需要打开文件的路径 文件名 参数flags表示选项O_RDONLY、O_WRONLY、O_RDWR必须包含这三个其中一个 参数mode表示权限如果传入0666就表示拥有者、所属组、other的权限都是rw- 选项有很多例如O_RDONLY只读、O_WRONLY只写、O_RDWR读写、O_CREAT文件不存在就创建、O_TRUNC打开文件时如果有原本内容就清空原始内容 像上面的这些是O_RDONLY、O_WRONLY、O_RDWR其实就是宏定义而open后面的参数只有一个flags如何传递这么多的标记位这里就和C中的位图类似了用比特位传递 关于open的返回值 如果成功了会返回一个文件描述符         如果失败了就会返回-1 关于两个open的使用场景: 三个参数的open是用于文件不存在第三个参数可以控制该文件的权限 两个参数的open是用于文件已经存在的场景 下面示范一下如何用比特位传递多个标记位 定义了三个宏A、B、C分别是0x1(0000 0001)、0x2(0000 0010)、0x4(0000 0100) main函数中给test传递的参数A | B就是0000 0001 | 0000 0010即传递上去的值为0000 0011 这时传递上去的0000 0011与A(0000 0001)B(0000 0010)按位与都满足所以会打印里面的语句 运行结果为 满足传上去的参数要求 这里的例子就说明了如果想传入多个标志位则用 | (按位或)的方式就能做到下面会用到这个结论 下面使用一下open 首先第一个umask是一个函数用于在当前进程重置umask值以便于我们open中传递的第三个关于权限的参数受到系统中umask值的影响 open中的第二个参数O_WRONLY | O_CREATO_WRONLY是以w的方式打开O_CREAT是创建一个文件如果文件不存在必须要加上O_CREAT选项中间的|在上面的例子中说到过传递多个标志位时用|连接 运行结果如下 成功运行 close 通过man查看close 这里的close使用就很简单了包含一个头文件unistd.h 关闭文件时将刚刚返回的文件标识符传入即可 代码中添加close即可 write 通过man查看write 包含一个头文件unistd.h 参数的含义就是向一个fd里写特定的buf字符个数是count个 下面演示用法 我们给了一个const char*类型的字符串使用write接口 运行结果如下 成功向文件中写入了I am write 但是这里会有一个问题我们在C语言中写入文件时如果文件中有内容再重写其他内容时会被覆盖而在Linux中则会存在问题如下 将字符串str改为111然后在运行查看现在test.txt中的内容 可以看到并不是我们所想的111而是111覆盖了刚刚内容的前三个字符的位置反而test.txt中的内容变为了111m write 想解决这个问题只需要加上选项O_TRUNC即创建文件时如果有原始内容则清空原始内容 如下所示 此时再重新运行打印test.txt中内容就变为我们想要的样子了 这里也应证了我们最开始所说的文件类的系统接口学习成本比较高难度比较大所以各种语言会封装文件接口使用起来更简单些 我们使用的   open(test.txt,O_WRONLY|O_CREAT|O_TRUNC,0666) 与C语言中的fopen(test.txt,w)的功能是一样的更看出其中的难易 上面用的是w的功能如果是a(追加)只需将O_TRUNC换为O_APPEND即可 这时多运行几次结果为 这时代码的open(test.txt,O_WRONLY|O_CREAT|O_APPEND,0666) 与C语言的fopen(test.txt,a)功能相同 read 通过man查看read 同样包含一个头文件unistd.h 参数的含义就是从特定的文件描述符fd读取数据读到buf里面读取的个数是count个 我们先向text.txt中写入数据 接着使用read 首先将open后面的参数变为O_RDONLY只读然后创建一个buf的字符数组memset将buf中的数据全部置为\0read读文件最后打印出读取的内容 最终读取成功 三、文件描述符 关于文件描述符fd上面的代码中有打印过接下来将代码做以改造多打开几个文件再观察文件描述符 创建4个test.txt文件观察每次返回的文件描述符fd 可以看到test.txt1~4的文件描述符分别是3、4、5、6那么为什么是从3开始的0、1、2是对应的什么其实在C语言中我们就学过了0、1、2分别对应的是stdin(标准输入)、stdout(标准输出)、strerr(标准错误)是被默认打开的 stdin、stdout、strerr他们的类型都是FILE*的 下面举例验证一下0、1、2这三个文件描述符 我们C语言中使用的fprintf如果要往显示器上写第一个参数就是stdout 而系统接口write第一个参数是fd我们可以传入1观察是不是往显示器上写入 结果为 可以发现传入文件描述符1也是往显示器上写入的与stdout功能相同 下面示例文件描述符为0的stdin 系统接口read的第一个参数传入0表示stdin read的返回值是读入的个数如果大于0就说明读入成功了 结果为 可以看到也可以通过传入文件描述符0实现stdin的功能 关于fd fd的本质是指针数组的下标 在内核中每一个进程都是可以打开多个文件的也就是一对多的关系 而为了管理这些文件操作系统需要构建一个file结构体包含了被打开文件的几乎全部内容如果被打开的文件很多就用双链表组织起来 而我们刚刚说到的0、1、2就是一个指针数组的下标表示这个指针数组前三个位置存储的就是stdin、stdout、stderr的位置Linux进程默认会打开这三个文件描述符0、1、2对应的物理设备一般是键盘、显示器、显示器 这里的指针数组中的每一个元素都是一个指向打开文件的指针 而我们上面所举例子中新创建了4个test.txt文件他们返回的fd分别是3、4、5、6也就代表着他们所在的位置就是这个指针数组的3、4、5、6下标在数组中做哈希索引索引之后就能找到被打开的文件对象 进程打开一个文件操作系统会创建一个struct file对象然后在该进程的指针数组中分配一个没有被使用的数组空间接着把新的文件地址填在这里面然后返回对应的文件描述符下标给用户使用所以fd在内核中本质是一个指针数组的下标 fd的分配规则 fd的分配规则是优先最小的没有被占用的文件描述符 正常情况下我们创建一个新文件文件描述符是3因为0、1、2是默认被打开的 结果为 如果我们提前把文件描述符0关了(close)那么新创建一个文件会被分配到哪个文件描述符 这时结果为 所以可以明白文件描述符基本的分配规则就是从头遍历找最小的且没有被占用的文件描述符 输出重定向示例 那么如果close的是1呢如图 创建test.txt前close(1)观察现象 我们运行myfile没有任何内容但是cat查看test.txt时却发现本该打印在显示器上的内容出现在了test.txt中 这是因为在我们创建test.txt前关闭了文件描述符1也就是系统默认打开的stdout它所对应的指针数组下标为1的位置为空了这时创建test.txt按照fd的分配原则将文件描述符1就分配给了test.txt 而我们所使用的printf、fprintf中都是包含stdout的所以执行时默认就是执行了stdout而stdout本身默认的文件描述符就是1刚刚分配文件描述符是底层做的上层并不清楚所以它们就照常往1里面写但是写完后通过进程找到指针数组再通过指针数组的下标1找到所对应的文件而这时1所对应的文件早已不是stdout而是test.txt因此我们printf的内容都在test.txt中可以看到 本来应该显示到显示器的内容被写入到了文件中这就是输出重定向 以上所说的就叫做重定向的原理 重定向的本质其实是在操作系统内部更改fd对应的内容的指向 输入重定向示例 先正常使用fgets函数观察正常打印的结果 创建了一个test.txt文件理应分配的文件描述符是3 并且下面的fgets第三个参数是stdin是从键盘读取的 所以先打印fd3然后在键盘输入hello显示器就打印了一个hello 上面是正常情况下面演示输入重定向的情况即close(0)时的情况 首先我们将test.txt的内容更改为hello test 然后在open文件test.txt前close(0): 这时根据fd的分配规则显然test.txt的文件描述符就分配为了0 运行结果为 可以看到打印出fd0但是接下来本应该从键盘读取却变为了直接读取文件test.txt的内容 原因也很简单我们close(0)后原本数组下标为0的的位置是指向stdin的现在变为了指向文件test.txt而上层并不知道底层做了这些改变在执行fgets时依然是从文件描述符0中读取而这时文件描述符已经变为了test.txt所以执行时根据文件描述符0指向的地址是test.txt的位置并不是stdin的所以不需要等待从键盘输入再打印而是直接打印test.txt的内容 而上面所说的本来应该从键盘中读取的内容变为了从文件中读取这就是输入重定向的定义 追加重定向示例 这是上面所举例的输出重定向 追加重定向只需将open中的参数O_TRUNC(清空)改为O_APPEND(追加)即可 这时看结果 第一次执行打印了原有的内容hello test且追加了fd1 又对执行了两次可以看到test.txt的内容也多了两行内容 这就是追加重定向 dup2函数 而我们如果想实现重定向上面的方法可以是可以但是比较麻烦下面说说更好的方法去实现重定向 首先学习函数dup2 dup2中有两个参数oldfd和newfd 关于这两个参数需要详细说明 oldfd是要拷贝到newfd中去所以最终会留下oldfd 所以如果我们创建一个文件这个文件的文件描述符就是3这时要进行输出重定向即将文件描述符1(stdout[显示器])改变指向所以需要将3拷贝到1中去最后留下的就是3即所创建的文件了 所以实现输出重定向使用dup2时oldfd是3newfd是1具体示例如下 使用fprintf时顺便复习一下命令行参数这时结果为 如果我们直接执行myfile这个可执行文件就进入第一行语句if (argc ! 2)中了因为此时只有myfileargc 1 接下来我们在myfile后面跟上了一个字符串这时就符合要求也打印出来了我们输入的字符串 以上是不使用dup2的情况下面使用dup2进行输出重定向 上面说到的第一个参数是oldfd第二个参数是newfd要保留oldfd所以我们传入fd即test.txt的fd 观察结果 dup2函数实现了输出重定向 dup2函数追加重定向 只需将open的第二个参数中的O_TRUNC变为O_APPEND即可 结果为 也能很轻松地实现 缓冲区 缓冲区就是一段内存空间 有缓冲区能够提高整机的效率也能够提高用户的响应速度 缓冲区的刷新策略 1、立即刷新 2、行刷新行缓冲例如遇到\n 3、满刷新全缓冲 也存在特殊情况 1、用户强制刷新例如fflush 2、进程退出 一般采用行缓冲策略的设备文件是显示器采用全缓冲策略的是磁盘 而所有的设备都是倾向于全缓冲的因为缓冲区满了才刷新IO操作少访问外设的次数变少从而提高效率 设备是倾向于全缓冲但是其他的刷新策略都是根据具体情况所做出的改变 例如显示器是行缓冲刷新是因为显示器是直接给用户看的需要照顾用户体验 下面看一个例子 先执行printf、fprintf、fputs然后执行write最后调用fork() 在调用fork()时上面的函数已经执行完毕了 下面观察结果 编译后直接运行myfile发现在显示器上打印的是4行 但是向普通文件打印时却变成了7行 通过观察可以发现C语言的接口是打印了两次的而系统接口只打印了一次 通过这个结果我们可以看出来执行fork()后并不影响系统接口所以如果存在缓冲区是由C标准库提供的而不是操作系统提供因为如果是操作系统提供的那么上面的结果应该是一样的write也应该打印两次 所以如果我们使用fprintf、fputs等接口应该是先写入C标准库的缓冲区中然后我们就不需要关心了何时刷新都是由C标准库管理的 而如果使用的是write接口就会直接将数据写给操作系统不需要经过缓冲区 下面说明上面代码在显示器上打印和重定向到文件中为什么结果不一样的原因 第一如果向显示器打印这时的刷新策略是行刷新每遇到一个\n就刷新一次那么最后执行fork的时候一定是函数执行完了并且数据已经被刷新了此时的fork无意义所以在显示器上打印时只有4个结果 第二 如果你进行了重定向就变为了要向磁盘文件打印这时的刷新策略变成了全缓冲所以printf、fprintf、fputs字符串后面的\n便没有意义了此时执行fork函数有父进程和子进程而父进程的数据还在缓冲区当中fork函数后面就执行return 0即进程退出 上面说到特殊情况进程退出时会刷新缓冲区而刷新的过程其实就是写入的过程可以理解为一个进程退出时为了不影响另一个进程使用现有的数据所以会发生写时拷贝所以我们明白了上面凡是在C标准库的缓冲区的数据都出现了两份而直接直接写给操作系统的系统接口只有一份 上面了解到之所以打印到显示器上内容和打印到文件里的内容不一样是因为打印到文件里时改变了刷新策略变为了全缓冲导致父进程的数据没有被刷新出来还保存在缓冲区中所以执行fork后发生写时拷贝打印出来了2份数据 那如果我们在fork前执行fflush函数强制刷新缓冲区这时执行fork时缓冲区中没有数据是不是就像我们所推测的那样上面两种方式打印的内容就相同了如下图 观察结果 通过观察可以发现执行完fflush后两种方式的打印的内容就完全相同了 stdout与stderr stdout与stderr对应的文件描述符分别是1和2 而1和2对应的都是显示器文件但是它们是不一样的 在输出或追加重定向时会有区别 我们分别在打印时加上-区别是1还是2 下面看结果正确运行时都能打印到显示器上 如果输出重定向 我们会发现往2号文件描述符写的内容依旧打印到显示器上了而只有往1号文件描述符写的内容才重定向到文件中 所以我们明白了这里的重定向其实是往1号文件描述符写的 1和2对应的都是显示器文件可以理解为打开了两份重定向时把正确的信息写到文件里错误信息依旧打印到显示器上 因此一般情况下如果程序可能存在问题建议使用stderr或cerr来打印 如果是常规的文本文件建议使用stdout或cout打印 针对标准输出和标准错误如果我们想将这两种分开打印可以进行如下操作 这时就可以将调用stdout的打印到right.txt中调用strerr的打印到err.txt中了 我们可以将标准输出和标准错误分开2err.txt就是将本来应该显示到2号文件描述符的内容显示到err.txt上 那如果我们就是想将stdout和stderr的内容都放在一个文件中就可以进行如下操作 这时就能实现上述要求 perror 上面代码中出现了perror这个函数其实我们可以发现使用perror后打印结果多了一个success其实这个函数会自动根据全局的错误码输出对应的错误原因 例如我们使用open时经常在下面的if语句里使用perror(open)就是表示如果open失败了可以打印失败的错误信息 假设我们使用open去读test文件if语句中使用perror 打印结果如下 通过ls可以发现当前路径下并没有test文件所以open的返回值小于0即进入if语句执行perror 通过结果可以看到perror会自动调用错误码输出错误信息例如上述例子的错误信息就是不存在该文件
http://www.tj-hxxt.cn/news/229293.html

相关文章:

  • 网站如何做单项链接网站建设自
  • 网站建设方面的销售经验做网站英文编辑有前途吗
  • 运营推广的网站有哪些网站404怎么做视频教程
  • 网站微信建设运营经验分享网站搭建的注意事项
  • 阿里云服务器创建多个网站在线做venn图网站
  • 网站怎么做微信登录江门网站建设junke100
  • 上海嘉定区网站建设公司二极管 东莞网站建设
  • 网站开发使用什么语言做淘宝一样的网站有哪些
  • 怎么做网站专题网站有关于我们的好处
  • 住房新建网站网站建设氺首选金手指13
  • 承德市建设局网站品牌建设口号
  • 佛山响应式网站公司厦门seo结算
  • 沧州工商联网站建设省内新闻最新消息
  • 公司做网站留言板创新网站建设工作
  • 什么网站做电子相册比加快电商seo搜索引擎优化
  • 县区网站服务器机房建设网站开发后服务费
  • 莱西网站建设哪家好旅游网站首页设计模板
  • 网站解析后 问题开创云网站建设支持
  • 简历制作网站哪个好网站建设计划书1200字
  • 河南网站建设公司哪个好呀wordpress 显示标签
  • 临沂网站设计公司网站优化 前端怎么做
  • 淄博网站建设电话咨询网站 三合一
  • 成都建设网站哪些公司好wordpress图片清晰度
  • 开了网站建设公司 如何接业务百度网站权重查询
  • 网站建设哪里招标wordpress 更改模板路径
  • 交换机可以做网站跳转吗网站建设需要很强的编程
  • 长春网站设计制作培训周口网站推广
  • 福州专业网站建设价格如何免费注册个人邮箱
  • 网站建设时间怎么查询能不能把wordpress程序转到帝国
  • 网站建设服务杭州好的app设计网站