出错处理
1 出错处理选项
代码段对出错处理有几种选择:
- 不做处理,这种方法不可取。
- 检测错误并向用户提供有关信息。
最好的一种出错处理选择是由Linux编程环境通过系统日志记录错误信息,这样可以永久地记录错误信息。
2 C语言机制
2.1 assert宏
宏assert的作用是如果它测试的条件返回错误(0),则终止程序执行。它先计算表达式expression,若其值为假,则先向stderr打印出错信息,然后调用函数abort来终止程序运行。
#include <assert.h>
void assert(int expression);
2.2 使用预编译
2.3 标准库函数
#include <stdlib.h>
void abort(void);
void exit(int status);
void atexit(void (*fun)(void));
#include <stdio.h>
void perror(const char *s);
#include <string.h>
char *strerror(int errnum);
#include <errno.h>
int errno;
errno变量:Linux系统调用(要求内核服务的函数)和许多库函数(大多数是在数学库中)在出错时都要把全局变量errno设置为一个非0值。未避免虚假出错情况,调用这些函数前最好先把errno清零。
宏 | 值 | 含义 |
---|---|---|
EPERM | 1 | 操作不允许 |
ENOENT | 2 | 文件或目录不存在 |
ESRCH | 3 | 进程不存在 |
EINTR | 4 | 系统调用中断 |
EIO | 5 | I/O错误 |
ENXIO | 6 | 设备或地址不存在 |
ECHILD | 10 | 子进程不存在 |
EAGAIN | 11 | 重试 |
ENOMEM | 12 | 没有内存 |
EACCES | 13 | 没有权限 |
EFAULT | 14 | 地址错误 |
EBUSY | 16 | 设备或资源忙 |
EEXIST | 17 | 文件存在 |
ENODEV | 19 | 设备不存在 |
ENOTDIR | 20 | 不是目录 |
EISDIR | 21 | 是目录 |
EINVAL | 22 | 无效参数 |
ENOSPC | 28 | 磁盘上没有空间 |
EPIPE | 32 | 管道中断 |
abort函数:会导致程序异常终止,故程序在被终止前不能进行一些常规的清除工作。abort会向系统返回一个预定义值以便告诉系统这是一个不成功的终止。
exit函数:exit与abort类似,但它完成清理工作后才终止程序。
atexit函数:登记程序正常终止时要调用的函数,由exit调用或由main函数返回调用。
strerror函数:返回指向字符串的指针,该字符串描述了与错误码相关的提示信息。
perror函数:首先打印字符串参数s,后跟一个冒号,一个空格,接着时对应于errno值得出错消息,最后是一个换行符。
3 使用系统日志
Linux使用两个守护进程klogd(内核和运行在内核空间的程序)和syslogd(用户程序)提供系统日志功能。
#include <syslog.h>
void openlog(const char *ident, int option, int facility);
void syslog(int priority, char *format, ...);
void closelog(void);
/* 使用实例 */
syslog(LOG_WARNING | LOG_USER, "unable to open file %s %m\n", fname);
/* 日志消息 */
Mar 26 19:36:25 user syslog: unable to open file foo
No such file or directory
3.1 openlog函数
可选择的,若不调用openlog,则第一次调用syslog时自动调用openlog。
ident:将被加至每则日志消息中,一般时程序的名称。
option:指定各种选项的为屏蔽。
facility:可让配置文件说明来自不同设施的消息将以不同的方式进行处理。
option | 说明 |
---|---|
LOG_PERROR | 除将日志消息发给syslogd以外,还将它写至标准出错 |
LOG_PID | 记录每条消息都要包含进程ID |
3.2 syslog函数
产生一个日志消息。
priority:优先级,由级别和功能共同组成,值为级别和功能的位逻辑或值。
级别(level) | 严重性 | 功能(facility) | 消息源 |
---|---|---|---|
LOG_EMRG | 系统不可用 | LOG_AUTH | 授权程序 |
LOG_ALERT | 要求立即处理 | LOG_CONSOLE | 消息写入/dev/console |
LOG_ERR | 错误条件 | LOG_DAEMON | 系统守护进程 |
LOG_WARNING | 警告条件 | LOG_KERN | 内核消息 |
LOG_NOTICE | 重要消息 | LOG_SECURITY | 安全子系统 |
LOG_INFO | 通报消息 | LOG_SYSLOG | syslogd内部消息 |
LOG_DEBUG | 调试或跟踪 | LOG_USER | 用户信息 |
format:指定写入日志的消息,特殊格式说明字符%m由strerror为errno分配的错误消息进行替换。
DEBUG | 调试或跟踪 | LOG_USER | 用户信息 |
format:指定写入日志的消息,特殊格式说明字符%m由strerror为errno分配的错误消息进行替换。