本节书摘来自异步社区《UNIX环境高级编程(第3版)》一书中的第1章,第1.7节,作者:【美】W. Richard Stevens , Stephen A.Rago著,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.7 出错处理

当UNIX系统函数出错时,通常会返回一个负值,而且整型变量errno通常被设置为具有特定信息的值。例如,open函数如果成功执行则返回一个非负文件描述符,如出错则返回1。在open出错时,有大约15种不同的errno值(文件不存在、权限问题等)。而有些函数对于出错则使用另一种约定而不是返回负值。例如,大多数返回指向对象指针的函数,在出错时会返回一个null指针。

文件中定义了errno以及可以赋与它的各种常量。这些常量都以字符E开头。另外,UNIX系统手册第2部分的第1页,intro(2)列出了所有这些出错常量。例如,若errno等于常量EACCES,表示产生了权限问题(例如,没有足够的权限打开请求文件)。

在Linux中,出错常量在errno(3)手册页中列出。
POSIX和ISO C将errno定义为一个符号,它扩展成为一个可修改的整形左值(lvalue)。它可以是一个包含出错编号的整数,也可以是一个返回出错编号指针的函数。以前使用的定义是:

extern int errno;

但是在支持线程的环境中,多个线程共享进程地址空间,每个线程都有属于它自己的局部errno以避免一个线程干扰另一个线程。例如,Linux支持多线程存取errno,将其定义为:

extern int *__errno_location(void); #define errno (*__errno_location())

对于errno应当注意两条规则。第一条规则是:如果没有出错,其值不会被例程清除。因此,仅当函数的返回值指明出错时,才检验其值。第二条规则是:任何函数都不会将errno值设置为0,而且在中定义的所有常量都不为0。

C标准定义了两个函数,它们用于打印出错信息。

#include <string.h>char *strerror(int errnum); 返回值:指向消息字符串的指针

strerror函数将errnum(通常就是errno值)映射为一个出错消息字符串,并且返回此字符串的指针。

perror函数基于errno的当前值,在标准错误上产生一条出错消息,然后返回。

#include <stdio.h> void perror(const char *msg);

它首先输出由msg指向的字符串,然后是一个冒号,一个空格,接着是对应于errno值的出错消息,最后是一个换行符。

实例
图1-8程序显示了这两个出错函数的使用方法。

#include "apue.h"
#include <errno.h>int
main(int argc, char *argv[])
{fprintf(stderr, "EACCES: %s\n", strerror(EACCES)); errno = ENOENT; perror(argv[0]); exit(0);
}

图1-8 例示strerror和perror

如果将此程序编译成文件a.out,然后执行它,则有

$ ./a.out
EACCES: Permission denied
./a.out: No such file or directory

注意,我们将程序名(argv[0],其值是./a.out)作为参数传递给perror。这是一个标准的UNIX惯例。使用这种方法,在程序作为管道的一部分执行时,例如:

prog1 < inputfile | prog2 | prog3 > outputfile
我们就能分清3个程序中的哪一个产生了一条特定的出错消息。

本书中的所有实例基本上都不直接调用strerror或perror,而是使用附录B中的出错函数。该附录中的出错函数使我们只用一条C语句就可利用ISO C的可变参数表功能处理出错情况。

出错恢复
可将在中定义的各种出错分成两类:致命性的和非致命性的。对于致命性的错误,无法执行恢复动作。最多能做的是在用户屏幕上打印出一条出错消息或者将一条出错消息写入日志文件中,然后退出。对于非致命性的出错,有时可以较妥善地进行处理。大多数非致命性出错是暂时的(如资源短缺),当系统中的活动较少时,这种出错很可能不会发生。

与资源相关的非致命性出错包括:EAGAIN、 ENFILE、 ENOBUFS、 ENOLCK、 ENOSPC、 EWOULDBLOCK,有时ENOMEM也是非致命性出错。当EBUSY指明共享资源正在使用时,也可将它作为非致命性出错处理。当EINTR中断一个慢速系统调用时,可将它作为非致命性出错处理(在10.5节对此会进行更多说明)。

对于资源相关的非致命性出错的典型恢复操作是延迟一段时间,然后重试。这种技术可应用于其他情况。例如,假设出错表明一个网络连接不再起作用,那么应用程序可以采用这种方法,在短时间延迟后,尝试重建该连接。一些应用使用指数补偿算法,在每次迭代中等待更长时间。

最终,由应用的开发者决定在哪些情况下应用程序可以从出错中恢复。如果能够采用一种合理的恢复策略,那么可以避免应用程序异常终止,进而就能改善应用程序的健壮性。

《UNIX环境高级编程(第3版)》——1.7 出错处理相关推荐

  1. Linux - Unix环境高级编程(第三版) 代码编译

    Unix环境高级编程(第三版) 代码编译 本文地址:http://blog.csdn.net/caroline_wendy 时间:2014.10.2 1. 下载代码:http://www.apuebo ...

  2. 《UNIX环境高级编程(第3版)》

    <UNIX环境高级编程(第3版)> 基本信息 原书名:Advanced Programming in the UNIX Environment (3rd Edition) (Addison ...

  3. UNIX环境高级编程(第三版 源码及编译好的静态库文件)

    UNIX环境高级编程(第三版) 源码 及 库文件 链接: https://pan.baidu.com/s/1tPY17lWNDEbzkOwZaRUUNg 提取码: 1024 复制这段内容后打开百度网盘 ...

  4. UNIX环境高级编程-第三版

    Unix环境高级编程-第三版 之前学习了<Linux系统编程>对于常见的概念和函数都有了基础的认知,这里准备通过这本书,深入学习系统API相关内容.笔记内容会有所倾向,不会严格反应书本内容 ...

  5. 开发日记-20190827 关键词 读书笔记《Unix环境高级编程(第二版)》DAY 3

    Referred Blogs 文件描述符标志,文件状态标志 Linux中文件描述符fd和文件指针flip的理解 Linux编程–文件描述符fd 文件共享 Unix支持在不同进程间共享文件. 内核使用了 ...

  6. 开发日记-20190822 关键词 读书笔记《Unix环境高级编程(第二版)》《掌控习惯》DAY 2

    Preface 话说,昨天开始尝试着去改变自己,从基础的习惯开始,11:30准时睡觉,平时差不多12:30才睡觉.按理说,比平时早了一个小时睡觉吧,然后我就把闹钟提前了45分钟,想着还能比平常多睡15 ...

  7. 开发日记-20190828 关键词 读书笔记《Unix环境高级编程(第二版)》DAY 4

    Part 1 文件与目录 设置用户ID和设置组ID 与一个进程相关联的ID有6个或更多. 实际: 实际用户ID/实际组ID 我们实际上是谁 有效: 有效用户ID/有效组ID/附属组ID 用于文件访问权 ...

  8. unix环境高级编程第三版源代码编译及使用

    估计好多学习unix/linux的程序员都知道有这么一本书,最近笔者也开始膜拜膜拜此书,在编译源代码的时候,遇到了一些问题,现在在这里做下总结,加深自己的印象,或许也有遇到此问题的同仁,可以参考参考! ...

  9. 开发日记-20190902 关键词 读书笔记《Unix环境高级编程(第二版)》DAY 7

    读目录 对某个目录具有存取许可权的单一用户都可读该目录,但是只有内核才能与目录(防止文件系统发生混乱).一个目录的写许可权位和执行许可权位决定了在该目录中是否能够创建新文件以及删除文件,它们并不表示能 ...

  10. 开发日记-20190820 关键词 读书笔记《Unix环境高级编程(第二版)》DAY 1

    Part 1:fork创建一个子进程过程 在父进程调用fork创建一个子进程.新进程是调用进程的复制品,故称调用进程为父进程,新创建的进程为子进程.fork对父进程返回非负进程ID,对子进程返回0.因 ...

最新文章

  1. latex中常使用符号大全
  2. DBA大牛告诉你,如何让MySQL语句执行加速?
  3. wcf返回json android,WCF返回JSON的详细配置
  4. CSS3学习笔记1:结构性伪类选择器
  5. JAVA程序设计----多线程(下)
  6. 向net core 3.0进击——Swagger的改变
  7. 利用浏览器调试功能 计算 百度网盘 文件数量
  8. Android查看web日志,详解Android WebView监听console错误信息
  9. SSM:Cause: java.sql.SQLSyntaxErrorException: ORA-00933: SQL 命令未正确结束的解决
  10. cloud一分钟 | 李飞飞离任谷歌云,工作重心将重新转回学术界
  11. Python super 函数 - Python零基础入门教程
  12. 留言系统 php 防攻击,php 留言板防刷新
  13. Sql根据不同条件统计总数
  14. java判断对象无数据_Java 判断实体对象及所有属性是否为空的操作
  15. 实现MINST图片的分类程序
  16. SpringBoot蚂蚁课堂-学习笔记
  17. eda交通灯控制器波形输入_EDA 基于quartus平台制作的步行街自助式交通灯控制器(含vhdl程序、波形图、及电路原理图)+课程设计报告...
  18. 谷歌浏览器设置跨域方法集合
  19. Scanner的close()方法的使用以及Scanner应该如何关闭
  20. 使用蓝湖UI效果图网站工具下载图标进行压缩

热门文章

  1. nginx反向代理,实现负载均衡
  2. 使用Windows 2008证书服务器为智能卡颁发证书
  3. Windows server 2003共享文件夹问题
  4. 【转】做正确的事情,等着被开除(Do the right thing, Wait to get fired)
  5. 2018.9.8-9.8 统计学课程笔记(2)-参数统计
  6. PHP设计模式——抽象工厂模式
  7. 解决Eclipse 启动后总是Building WorkSpace(sleeping)
  8. 从明天起,做一个幸福的人。喂马,砍柴,周游世界
  9. Weblogic 9.2和10.3 改密码 一站完成
  10. App列表之圆角ListView源码