zoukankan      html  css  js  c++  java
  • UNIX基础知识之出错处理

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

      文件<errno.h>中定义了符合errno以及可以赋予它的各种常量,这些常量都以字符E开头。另外,UNIX系统手册第2部分的第1页intro(2)列出了所有这些出错常量。在Linux中,出错常量在errno(3)手册页中列出(可以使用命令man 3 errno查看)。

      POSIX和ISO C将errno定义为这样一个符号,它扩展成为一个可修改的整型左值(lvalue)。这可以是包含出错编号的一个整数,或者是一个返回出错编号指针的函数。以前使用的定义是:

    extern int error;

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

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

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

      (1)如果没有出错,则其值不会被一个例程清除。因此,仅当函数的返回值指明出错时,才检验其值。

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

      C标准定义了两个函数,它们帮助打印出错信息:

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

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

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

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

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

      程序清单1-6 示例strerror和perror

    [root@localhost unix_env_advance_prog]# cat prog1-6.c
    #include "apue.h"
    #include <errno.h>
    
    int
    main(int arg, char *argv[])
    {
            fprintf(stderr, "EACCES: %s
    ", strerror(EACCES));
            errno = ENOENT;
            perror(argv[0]);
            exit(0);
    }

      编译后执行此程序:

    [root@localhost unix_env_advance_prog]# ./prog1-6
    EACCES: Permission denied
    ./prog1-6: No such file or directory

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

    prog1 < inputfile | prog2 | prog3 >outputifle

      我们就能分清三个程序中的哪一个产生了一条特定的出错信息。

    出错恢复

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

      与资源相关的非致命性出错包括EAGAIN、ENFILE、ENOBUFS、ENOLCK、ENOSPC、ENOSR、EWOULDBLOCK,有时ENOMEM也是非致命性出错。当EBUSY指明共享资源正在使用时,也可将它作为非致命性出错处理。当EINTR中断一慢速系统调用时,可将它作为非致命性出错处理。

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

      最后,取决于应用程序的开发者,他可以决定哪些出错是可以恢复的。如若使用一种从错误中恢复的合理策略,那么由于避免了应用程序的异常终止,就能改善应用程序的健壮性。

    本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

  • 相关阅读:
    【转】全文检索引擎Sphinx配置文件详细介绍
    【转】构建不依赖于cookie的手机端用户登录机制
    Sphinx在window下的初步安装和配置
    Zend Framework 在.htaccess中修改RewriteRule实现url重写
    做后台的程序猿的一点心得
    [Leetcode 75] 96 Unique Binary Search Trees
    [Leetcode 74] 92 Restore IP Addresses
    [Leetcode 73] 92 Reverse Linked List II
    [Leetcode 72] 91 Decode Ways
    [Leetcode 71] 86 Partition List
  • 原文地址:https://www.cnblogs.com/nufangrensheng/p/3495426.html
Copyright © 2011-2022 走看看