《UNIXLinux程序设计教程》一1.6 错误处理

简介: 本节书摘来自华章出版社《UNIXLinux程序设计教程》一 书中的第1章,第1.6节,作者:赵克佳 沈志宇,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

1.6 错误处理

UNIX的系统调用和大部分库函数在失败时会返回一特殊值报告出错,这个特殊值通常是–1。这种返回值仅告诉调用遇到了错误而已,为了让应用知道究竟发生了什么错误,系统调用和库函数同时还会在系统定义的变量errno中给出指明错误原因的错误码。
变量errno是系统调用和库函数用来报告错误的一种标准方法。早期的UNIX和C将它实现为外部整型变量,其说明为:

extern int errno;

这是进程中的全局共享变量,无法支持多线程。为了支持多线程,新的POSIX标准和C标准在要求这个变量为整型左值的同时,还规定一个线程对errno的读写不受其他线程更改errno的影响。因此,新的UNIX和C实现已经改变为每个线程各自有自己对应的errno。例如,Linux将其定义为:

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

这样,每个线程便可通过内建的专门函数获得各自errno的存储单元。
头文件定义了变量errno以及它可以取值的错误码。每一种错误码有一个符号名,它们是定义在中以字母'E'开头的宏名字。所有错误码的值都是正整数且除了EWOULDBLOCK和EAGAIN之外每一个都互不相同。因此,可以用它们作为switch语句内的case标号来区分错误情形。表1-1列出了一些常见的错误码。
程序开始时,变量errno的初值一定是0,UNIX的系统调用和许多库函数当遇到错误时均保证设置该变量为某个非0值。errno的值只有在函数调用出错时才被设置,函数调用成功则不会改变,它可能是前一次调用某个函数出错时的值。因此,不应当用errno来检测一个调用是否失败。正确的做法是仅当函数的返回值指出这个变量被明显设置时才用errno来确定错误原因。
screenshot

不会有任何函数设置errno的值为0来指出错误,errno的这个性质可以用来检测某些特殊函数的错误返回值。有少数函数,如1.8.3节介绍的pathconf(),在出现错误的情况下仍返回一个合法值,但同时也设置errno。对于这些函数,如果我们想检测是否遇到了错误,应当在调用它们之前置errno为0,函数调用之后再检查其值。我们在程序1-3中会见到这种情况的例子。
errno的错误码是整数,C标准函数strerror()可将错误码转换为可读的报错信息。

#include <string.h>
char *strerror(int errnum);
 

strerror()返回与errnum错误码相对应的错误信息字符串。我们不能修改由strerror()返回的字符串,同样,如果紧接着再次调用strerror(),前一次调用得到的字符串将被覆盖。
如果想直接将errno当前值对应的错误信息输出到标准报错文件,则可调用perror()。

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

perror()首先打印msg指定的信息,后随一个冒号和空格,然后打印与errno对应的错误字符串。
如果msg是空指针或指向空字符串,perror()打印的将是与strerror()完全相同的信息,但perror()附加有换行符,而strerror()没有。
例1-1 当系统调用或库函数发生错误时,在有些情况下会需要立即终止程序的运行,因为继续执行已没有意义。此时,可以用perror()或strerror()这两个函数之一打印出对应的错误信息,然后调用exit(1)终止程序的执行。本书的很多例子就是这种情况。为此,我们统一使用一个函数err_exit()来完成报告错误并退出的动作。这个函数以宏方式定义在我们的头文件err_exit.h(程序1-1)中,其中,宏调用参数MESSAGE给出用户需要输出的信息。
screenshot

本书在介绍每一个函数时,有时会省略返回值的说明,此时除非特殊说明,均遵循UNIX的一般约定:调用成功的返回值是0,错误返回值是–1,并设置了错误码于errno中。

相关文章
|
6天前
|
缓存 网络协议 Unix
Linux(UNIX)五种网络I/O模型与IO多路复用
Linux(UNIX)五种网络I/O模型与IO多路复用
116 0
|
10月前
|
Unix Linux C语言
计算机操作系统实验一 Unix/Linux编程开发环境
计算机操作系统实验一 Unix/Linux编程开发环境
106 0
|
6天前
|
Unix Shell Linux
在Unix/Linux操作系统中,Shell脚本广泛用于自动化任务
在Unix/Linux操作系统中,Shell脚本广泛用于自动化任务
30 2
|
6天前
|
Unix Shell Linux
在Linux和类Unix系统中,Shell提供了多种命令用于用户和权限管理
在Linux和类Unix系统中,Shell提供了多种命令用于用户和权限管理
38 4
|
6天前
|
Oracle Ubuntu Unix
Unix与Linux区别
Unix: Unix是一个操作系统家族的名称,最早由贝尔实验室(Bell Labs)的肖像电机公司(AT&T)开发。最早的Unix版本是在1969年创建的。 Linux: Linux是由芬兰计算机科学家Linus Torvalds在1991年创建的。它是作为一个免费、开放源代码的Unix克隆而开始的。
20 1
|
6天前
|
Unix Shell Linux
在Unix/Linux Shell中,管道(`|`)和重定向
在Unix/Linux Shell中,管道(`|`)和重定向
26 1
|
8月前
|
Unix 大数据 Linux
【Linux is not Unix】Linux前言
【Linux is not Unix】Linux前言
|
6天前
|
Ubuntu Unix Linux
Unix/Linux操作系统的最强入门科普(经典)
Unix/Linux操作系统的最强入门科普(经典)
105 0
|
6天前
|
网络协议 Unix Linux
在Unix/Linux shell中,与网络相关的命令
在Unix/Linux shell中,与网络相关的命令
29 2
|
6天前
|
监控 Unix Linux
在Linux和类Unix操作系统中,`top` 命令
在Linux和类Unix操作系统中,`top` 命令
33 2