Linux 系统应用编程——出错处理(errno)

来源:互联网 发布:mac sunlime3 注册码 编辑:程序博客网 时间:2024/05/21 22:05

1. errno变量
     文件 <errno.h> 中定义了符号 errno 以及可以赋予它的各种常量,这些常量都是以字符 E 开头。例如,若 errno 等于常量 EACCES,表示产生了权限问题(例如,没有打开所要求文件的足够权限)。

      当 UNIX 函数出错时,常常返回一个负值,而且将整型变量 errno 设置成含有附加信息的各个常量。例如,open 函数如果成功执行则返回一个非负文件描述符,如出错则返回 -1。在 open 出错时,有大约 15 种不同的errno 值(文件不存在、权限问题等)。

对于 errno 应该知道两条规则:

规则一:如果没有出错,则errno的值不会被一个例程清除。
因此,仅当函数的返回值指明出错时,才校验 errno 的值。

规则二:任一函数都不会将errno的值设置为0,在<errno.h>中定义的所有常量都不为0。

 

出错标志 errno 是一个整型数值,这个对于用户提示不够有好。C 标准定义了两个函数,用于帮助打印出错信息:

1)、strerror()

[cpp] view plain copy
  1. #include <string.h>  
  2. #include <errno.h>  
  3.   
  4. char *strerror(int errnum);  

返回值:指向消息字符串的指针

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

2)、perror()
perror 函数基于 errno 的当前值,在标准出错上产生一条出错信息,然后返回。

[cpp] view plain copy
  1. #include <stdio.h>  
  2.   
  3. void perror(const char *msg);  

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

例子:

下面代码展示了这两个出错函数的使用方法::

[cpp] view plain copy
  1. #include <string.h>  
  2. #include <stdio.h>  
  3. #include <errno.h>  
  4. #include <stdlib.h>  
  5. int  
  6. main(int argc, char *argv[])  
  7. {  
  8.     fprintf(stderr, "EACCES: %s\n", strerror(EACCES));  
  9.     errno = ENOENT;  
  10.     perror(argv[0]);  
  11.     exit(0);  
  12. }  

执行结果如下:

[cpp] view plain copy
  1. fs@ubuntu:~/qiang/error$ ./error   
  2. EACCES: Permission denied  
  3. ./error: No such file or directory  
  4. fs@ubuntu:~/qiang/error$   

 
2. 打印所有错误信息

C 标准库定义了sys_nerr 用于记录错误信息总个数,下面程序通过循环来打印所有信息。

[cpp] view plain copy
  1. #include <string.h>  
  2. #include <stdio.h>  
  3. #include <errno.h>  
  4. #include <stdlib.h>  
  5. int main(int argc, char *argv[])  
  6. {  
  7.     int idx = 0;  
  8.     for (idx = 0; idx < sys_nerr; idx++) {  
  9.         printf("Error #%3d: %s\n", idx, strerror(idx));  
  10.     }  
  11.     exit(0);  
  12. }  

执行结果如下:

[cpp] view plain copy
  1. fs@ubuntu:~/qiang/error$ ./print_err   
  2. Error #  0: Success  
  3. Error #  1: Operation not permitted  
  4. Error #  2: No such file or directory  
  5. Error #  3: No such process  
  6. Error #  4: Interrupted system call  
  7.   
  8. ....  
  9.   
  10. Error #132: Operation not possible due to RF-kill  
  11. Error #133: Unknown error 133  
  12. Error #134: Unknown error 134  
  13. fs@ubuntu:~/qiang/error$   


3. 多线程扩展
在支持线程的环境中,多个线程共享进程地址空间,每个线程都有属于它自己的局部 errno 以避免一个线程干扰另一个线程。

函数 strerror() 不是线程安全的。因为该函数将 errnum 对应的字符串保存在一个静态的缓冲区中,然后将该缓冲区的指针返回。另一个线程调用 strerror() 就会重新设置静态缓冲区的内容。

 

4. 出错恢复
可将 <errno.h> 中定义的各种出错分成致命性的和非致命性的两类。对于致命性的错误,无法执行恢复动作,最多只能在用户屏幕上打印出一条出错信息,或者将一条出错信息写入日志文件,然后终止。而对于非致命性的错误,有时可以较妥善地进行处理。

0 0