附录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. INFORMATICA 的部署实施 MTP&MTS

    软件开发的一般都有三个环境,开发环境,用户接受度测试环境,生产环境.我最近实施了从开发环境到生产环境的部署工作,在此跟大家分享一下. 大概步骤如下: 1 备份生产环境INFORMATICA 知识库  ...

  2. Effective Java 72 Don't depend on the thread scheduler

    Principle Any program that relies on the thread scheduler for correctness or performance is likely t ...

  3. 【php】使用phpdbg来调试php程序

    PHPDBG是一个PHP的SAPI模块,可以在不用修改代码和不影响性能的情况下控制PHP的运行环境 可以在PHP5.4和之上版本中使用.在PHP5.6和之上版本将内部集成 功能 单步调试 灵活的下断点 ...

  4. ehcache整合spring注解方式

    一.简介 在hibernate中就是用到了ehcache 充当缓存.spring对ehcache也提供了支持,使用也比较简单,只需在spring的配置文件中将ehcache的ehcache.xml文件 ...

  5. poj 2195 KM算法

    题目链接:http://poj.org/problem?id=2195 KM算法模板~ 代码如下: #include "stdio.h" #include "string ...

  6. linux—【绝对路径与相对路径】与【【文件基本操作】】(4)

    [绝对路径与相对路径] 绝对路径:我们在获得一个文件的时候,从根目录到二级到更多级目录都写全了, 终才找到这个文件,这种方式就是“绝对路径” 相对路径:目标文件与我本身文件的相对位置 当前目录:./  ...

  7. centos7下docker 部署javaweb

    LXC linux container 百度百科:http://baike.baidu.com/link?url=w_Xy56MN9infb0hfYObib4PlXm-PW02hzTlCLLb1W2d ...

  8. excel if判断时间段早晚班

    =IF(OR(HOUR(B3)={9,10,11,12,13,14,15,16,17,18}),"早班","晚班")

  9. Linux运维式具之pdsh

    做系统运维的时候,我们经常需要同时在多台机器上执行相同的命令,这个时候可以使用类似pssh,pdsh的并行执行shell的工具. 当然,之前在没有使用这些工具之前,如果有ssh无密码互访,我们可以自己 ...

  10. css中元素居中总结

    很多时候,我们需要让元素居中显示:1. 一段文本的水平居中,2. 一张图片的水平居中,3. 一个块级元素的水平居中:4. 单行文本的竖直居中,5. 不确定高度的一段文本竖直居中,6. 确定高度的块级元 ...