附录A  错误处理

A.1 Unix系统中的错误处理

1.Unix风格的错误处理

if ((pid = wait(NULL)) < 0) {

fprintf(stderr,”wait error:%s\n”,strerror(errno)));

exit(0);

}

strerror函数返回某个errno值的文本描述。

2.Posix风格的错误处理

if ((retcode = pthread_create(&tid,NULL,thread,NULL))!= 0){

fprintf(stderr,”pthread_create error:%s\n”,

strerror(retcode));

exit(0)

}

3.DNS风格的错误处理

if ((p = gethostbyname(name)== NULL){

fprintf(stderr, “gethostbyname error:%s\n:”,

hstrerror(h_errno));

exit(0);

}

正如他们的名字表明的那样,unix_error、posix_error和dns_error函数报告Unix风格的错误、Posix风格的错误和DNX风格的错误,然后终止。包括app_error函数是为了方便报告应用错误。它只是简单地打印它的输入,然后终止。

A.2 错误处理包装函数

1Unix风格的错误处理包装函数

2Posix风格的错误处理包装函数

3DNS风格的错误处理包装函数

第十章  系统级I/O

输入/输出(I/O)是在主存和外部设备(如磁盘驱动器、终端和网络)之间拷贝数据的过程。输入操作是从I/O设备拷贝数据到主存,而输出操作是从主存拷贝数据到I/O设备。

10.1 UnixI/O

一个Unix文件就是一个m字节的序列:

B0,B1,B2,B3,……,Bk,Bm-1

所有的I/O设备,如网络、磁盘和终端。都被模型化为文件,而所有的输入和输出都被当做对相应文件的读和写来执行。这种将设备优雅地映射为文件的方式,允许Unix内核引出一个简单、低级的应用接口,称为UnixI/O,这使得所有的输入和输出都能以一种统一且一致的方式来执行:

·打开文件

·改变当前的文件位置

·读写文件

·关闭文件

10.2打开和关闭文件

进程通过调用open函数来打开一个已存在的文件或者创建一个新文件的:R

open函数将filename转换成一个文件描述符,并且返回描述符数字。返回的描述符总是在进程中没有打开的最小描述符。

Flags参数指明了进程打算如何访问这个文件:

  • O_RDONLY:只读
  • O_WRONLY:只写
  • O_RDWR:可读可写

Flags参数也可以是一个或者更多位掩码的或,为写提供给一些额外的指示:

  • O_CREAT:如果文件不存在,就创建它的一个截断的(空)文件。
  • O_TRUNC:      如果文件已经存在,就截断他。
  • O_APPEN      D:在每次写操作前,设置文件位置到文件的结尾处。

Mode参数指定了新文件的访问权限位。

最后进程通过调用close函数关闭一个打开的文件。

关闭一个已关闭的描述符会出错。

10.3读和写文件

#include<unistd.h>

ssize_t read(int fd,void *buf,size_t n);/*返回:若成功则为读的字数,0为EOF,-1为出错*/

ssize_ write(int fd,const void *buf,size_t n);/*返回:若成功则为写的字节数,若出错则为-1*/

1.read函数

从描述符fd的当前文件位置拷贝n个字节到存储位置buf。

2.write函数

从存储器位置buf拷贝至多个n字节到描述符fd的当前文件位置

3.lseek函数

通过调用lseek函数,应用程序能够显式地修改当前文件的位置。

△不足值

read和write传送的字节比应用程序要求的要少。

出现情况如下:

  • 读时遇到EOF
  • 从终端读文本行      (返回不足值为文本行大小)
  • 读和写网络套字(socket)
    1. 内存缓冲约束和较长的网络延迟
    2. Unix管道

应用程序是通过分别调用系统函数 read和write函数来执行输入和输出的。

旁注:size_t是作为usigned int,而ssize_t是作为int。

在某些情况下,read和write传送的字节比应用程序要求的要少。出现这种情况的可能的原因有:

读时遇到EOF。假设该文件从当前文件位置开始只含有20个字节,而应用程序要求我们以50个字节的片进行读取,这样一来,这个read的返回的值是20,在此之后的read则返回0。
从终端读文本行。如果打开的文件是与终端相关联的,那么每个read函数将一次传送一个文本行,返回的不足值等于文本行的大小。
读和写socket。如果打开的文件对应于网络套接字,那么内部缓冲约束和较长的网络延迟会导致read和write返回不足值。

10. 4 用RIO包健壮地读写

RIO包会自动为你处理上文中所述的不足值。

RIO提供了两类不同的函数:

  • 无缓冲的输入输出函数。
  • 带缓冲的输入函数。

10.4.1 RIO的无缓冲的输入输出函数

通过调用rio_readn和rio_writen函数,应用程序可以在存储器和文件之间直接传送数据。

注意:如果rio_readn和rio_writen函数被一个从应用信号处理程序的返回中断,那么每个函数都会手动地重启read或write。

10.4.2 rio的带缓冲的输入函数 600

  • 一个文本行就是一个由      换行符 结尾的ASCII码字符序列。在Unix系统中,换行符是‘\n’,与ASCII码换行符LF相同,数值为0x0a。假设我们要编写一个程序来计算文本文件中文本行的数量应该如何来实现呢?

一种方法是用read函数来一次一个字节地从文件传送到用户存储器,检查每个字节来查找换行符。这种方法的问题就是效率不高,每次取文件中的一个字节都要求陷入内核。
一种更好的方法是调用一个包装函数(rio_readlineb),它从一个内部缓冲区拷贝一个文本行,当缓冲区变空时,会自动的调用read系统调用来重新填满缓冲区。

  • 在带缓冲区的版本中,每打开一个描述符都会调用一次rio_readinitb函数,它将描述符fd和地址rp处的一个类型为rio_t的读缓冲区联系起来。
  • rio_readinitb函数从文件rp读取一个文本行(包括结尾的换行符),将它拷贝到存储器位置usrbuf,并且用空字符来结束这个文本行。
  • RIO读程序的核心是rio_read函数,rio_read函数可以看成是Unix read函数的带缓冲区的版本。当调用rio_read要求读取n个字节的时候,读缓冲区内有rp->rio_cnt个未读的字节。如果缓冲区为空的时候,就会调用read系统函数去填满缓冲区。这个read调用收到一个不足值的话并不是一个错误,只不过读缓冲区的是填充了一部分。
  • 一旦缓冲区非空,rio_read就从读缓冲区拷贝n和rp->rio_cnt中较小值个字节到用户缓冲区,并返回拷贝字节的数目。
  • 对于应用程序来说,rio_read和系统调用read有着相同的语义。出错时返回-1;在EOF时,返回0;如果要求的字节超过了读缓冲区内未读的字节的数目,它会返回一个不足值。rio_readlineb函数多次调用rio_read函数。每次调用都从读缓冲区返回一个字节,然后检查这个字节是否是结尾的换行符。
  • rio_readlineb函数最多读取(maxlen-1)个字节,余下的一个字节留给结尾的空字符。超过maxlen-1字节的文本行被截断,并用一个空字符结束。

10.5 读取文件元数据

应用程序能够通过调用stat和fstat函数,检索到关于文件的信息(元数据)

#include <unistd.h>
#include <sys/stat.h>
 
int stat(const char *filename, struct stat *buf);
int fstat(int fd,struct stat *buf);/*返回:成功返回0,若出错则为-1*/

stat以文件名作为输入,fstat以文件描述符作为输入

普通文件

某种类型的二进制或文本数据(对内核而言两者并没有什么区别)

目录文件

包含关于其他文件的信息

套接字

一种用来通过网络和其他进程通信的文件

st_size

包含了文件的字节数大小。

st_mode

编码了文件访问许可位和文件类型。
Unix提供的宏指令根据st_mode成员来确定文件的类型。

10. 6 共享文件

内核用三个相关的数据结构来表示打开的文件:

  • 描述符表。
  • 文件表。
  • V-node表。

10.7 i/o重定向 608

  • Unix外壳提供了I/O重定向操作符,允许用户将磁盘文件和标准输入输出联系起来。
  • I/O重定向的工作方式: 一种是使用dup2函数。
  • dup2函数拷贝描述符表表项oldfd到描述符表表项newfd,覆盖描述符表表项newfd以前的内容。如果newfd已经打开了,dup2会在拷贝oldfd之前关闭newfd。

10.8 标准I/O

标准I/O库:

打开和关闭文件的函数fopen fclose

读和写字节的函数fgets fputs

复杂格式化的I/O函数scanf printf

流:一个流就是一个指向FILE类型结构的指针

每个ANSI C程序开始时都有三个打开流:

stdio   标准输出

stdout  标准输入

stderr  标准错误

FILE类型流是对文件描述符流缓冲区的抽象

流缓冲区的目的:
使开销较高的Unix I/O系统调用的数量尽可能小。

重点

    1. 阅读教材,注意每个系统调用的参数、返回值,会查帮助文档
      完成课后练习(书中有参考答案)重点:10.1、10.2、10.3、10.4、10.5
    2. 重要命令:
      man -k key1 | grep key2| grep 2 : 根据关键字检索系统调用
      grep -nr XXX /usr/include :查找宏定义,类型定义

参考资料

    1. 教材:第十章,详细学习指导:http://group.cnblogs.com/topic/73069.html
    2. 课程资料:https://www.shiyanlou.com/courses/413 实验十,课程邀请码:W7FQKW4Y
    3. 教材中代码运行、思考一下,读代码的学习方法:http://www.cnblogs.com/rocedu/p/4837092.html。

20135306黄韧 附录A及第十章学习总结的更多相关文章

  1. 20135306黄韧[2.72 2.77 3.70](http://i.cnblogs.com/EditPosts.aspx?opt=1)

    2.72 A.size_t是无符号整数,因此左边都会先转换为无符号整数,它肯定是大于等于0的. B.判断条件改为 if(maxbytes > 0 && maxbytes > ...

  2. 鸟哥的linux私房菜——第十章学习(BASH)

    第十章 BASH 1.0).认识BASH 作用:通过" Shell "可以将我们输入的指令与 Kernel 沟通,好让Kernel 可以控制硬件来正确无误的工作! 应用程序其实是在 ...

  3. 20165233 Java第七、十章学习总结

    20165233 2017-2018-2 <Java程序设计>第五周学习总结 教材学习内容总结 ch07 内部类:Java支持在一个类中声明另一个类,这样的类称为内部类,而包含内部类的类称 ...

  4. 《深度学习》Textbook第十章学习笔记

    深度学习 第10章 序列建模:循环和递归网络 1.循环神经网络介绍 相比卷积神经网络:专门用于处理网格化的数据(如图像),可以很容易扩展到更具有很大宽度和高度的图像,以及处理大小可变的图像: 循环神经 ...

  5. 201671010142 2017-2 《java第十章学习感悟》

    组件:Java把由Component类的子类或间接子类创建的对象称为一个组件. 容器:是Java中能容纳和排列组件的组件. Container类提供了一个方法add(),用来在容器类组件对象中添加其他 ...

  6. Mudo C++网络库第十章学习笔记

    C++编译链接精要 C++语言的三大约束: 与C兼容, 零开销(zero overhead)原则, 值语义; 兼容C语言的编译模型与运行模型, 也就是锁能直接使用C语言的头文件和库; 头文件包含具有传 ...

  7. 20135306 2.4 ELF文件格式分析

    2.4   ELF文件格式分析 20135306 黄韧 ELF全称Executable and Linkable Format,可执行连接格式,ELF格式的文件用于存储Linux程序.ELF文件(目标 ...

  8. 信息安全系统设计基础第一次实验报告 20135201&&20135306&&20135307

    信息安全系统设计基础实验 班级: 201353 姓名:张忻 张嘉琪 黄韧 学号:20135301 20135307 20135306 实验日期:2015.11.10 实验名称: S3C2410的lin ...

  9. 20175320 2018-2019-2 《Java程序设计》第6周学习总结

    20175320 2018-2019-2 <Java程序设计>第6周学习总结 教材学习内容总结 本周学习了教材的第七及第十章的内容.在这两章中介绍了接内部类与异常类以及输入.输出流,第七章 ...

随机推荐

  1. 整理了一些常用的jQuery动画事件

    部分jQuery常用的动画函数,整理了一下,在做交互式页面的时候挺有用的 .css('a','12px');.css({  a:'12px',  b:'#fff'}); .show();.hide() ...

  2. Effective Java 42 Use varargs judiciously

    Implementation theory The varargs facility works by first creating an array whose size is the number ...

  3. SeekableByteChannel 和 FileChannel

    Java7中引入了SeekableByteChannel接口,允许我们定位到文件的任意位置进行读写.注意这里的写,不是新增式的插入,而是覆盖,当然在文件末尾的写,是新增. java.nio.chann ...

  4. 删除CListCtrl中具有某一相同数据的所有行

    删除CListCtrl中具有某一相同数据的所有行 ================================== 本文原创,转载请注明出处:http://blog.csdn.net/wlsgzl ...

  5. UVALive - 2965 Jurassic Remains (LA)

    Jurassic Remains Time Limit: 18000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu [Sub ...

  6. Can't initialize metastore for hive

    there maybe many reason to cause this,today our issue is that, if you execute hive –database dbname ...

  7. 详解Webwork中Action 调用的方法

    详解Webwork中Action 调用的方法 从三方面介绍webwork action调用相关知识: 1.Webwork 获取和包装 web 参数 2.这部分框架类关系 3.DefaultAction ...

  8. 前端的瑞士军刀:Modernizr.js

    前言 Modernizr.js既能给老版本浏览器打补丁,又能保证新浏览器渐进增强的用户体验. 作用: 从实际操作来看,Modernizr默认做的事情很少,除了(在你选择的情况下)给不支持html5的标 ...

  9. CSS3实现气泡效果

    首先定义一个 <p class="speech"></p> 先给外层的容器添加样式: p.speech { position: relative; widt ...

  10. [ORACLE错误]oracle 不能更新 PL/SQL 点击“edit data”报“ these query results are not updateable”

    你可以选择在查询语句的最后加上 for update,就可以打开编辑锁,直接修改数据. 而在默认查询下,点击Edit data,会报错:The query results are not update ...