zoukankan      html  css  js  c++  java
  • shell环境

    1 引言

      一个进程运行在shell环境中,理解进程运行的环境是十分重要的。环境影响着进程的行为,利用环境提供的便利,可以极大地提高开发效率。本节深入讨论shell中与进程有关的环境问题,包括命令行参数、环境变量和错误号变量等。


    2 命令行参数

    2.1 简介

      当一个新进程执行时,命令行参数和环境变量是两个非常重要的信息。这两个信息都是新进程从产生它的父进程那里获得的,其获得方式也有不同。命令行参数作为main函数的参数被传入到新进程中,而环境变量是作为一种全局变量被新进程所使用的。

      对于C语言来说,程序的执行时从main函数开始的。main函数的原型如下:

    int main(int argc, char * argv[])

      其中,argc是命令行参数的个数,argv是指向参数的字符串指针数组,其中每一个元素都是一个字符串,以‘’结尾。在执行一个程序的时候,调用exec()函数的进程会把命令行参数传递给新程序。下面的示例程序就是打印命令行参数:

     1 //print command line parameters to stdout 
     2 #include <stdio.h>
     3 
     4 int main(int argc, char * argv[]) 
     5 { 
     6     int i;
     7 
     8     printf("Counts of arguments: %d
    ", argc); 
     9     for (i = 0; i < argc; i++) 
    10         printf("argv[%d]: %s
    ", i, argv[i]);
    11 
    12     return 0; 
    13 }
    main.c

    程序运行结果如下:

    xiaomanon@xiaomanon-machine:~/Documents/c_code$ gcc main.c -o app 
    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./app -o yes ok 23 
    Counts of arguments: 5 
    argv[0]: ./app 
    argv[1]: -o 
    argv[2]: yes 
    argv[3]: ok 
    argv[4]: 23 

    2.2 获取文件名

       命令行参数数组的第一个元素(即argv[0])是程序的路径名,并不是该程序的文件名。如果希望在程序中使用该程序文件的文件名,则需要做特殊处理。下面实现了一个获取程序文件名的函数,这个函数以一个文件的路径为参数,并且寻找该路径中的最后一个“/”,那么这个“/”右边就是函数需要找的程序文件名。

     1 //get program file name 
     2 #include <stdio.h> 
     3 #include <string.h>
     4 
     5 char* getFileName(char* fullName) 
     6 { 
     7     char *p; 
     8     //find the last symbol '/' from fullName 
     9     p = rindex(fullName, '/'); 
    10     if (p == '') 
    11         p = fullName;//it is already a file name 
    12     else 
    13         p++;//move to next position
    14 
    15     return p; 
    16 }
    17 
    18 int main(int argc, char * argv[]) 
    19 { 
    20     char *p;
    21 
    22     p = getFileName(argv[0]); 
    23     printf("directory: %s
    ", argv[0]); 
    24     printf("file name : %s
    ", p);
    25 
    26     return 0; 
    27 }
    main.c

    程序运行结果如下:

    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./app 
    directory: ./app 
    file name : app

    注意:argv[argc]是一个NULL指针,这一点不会由机器自动完成,但是此定义遵守ISO C。所以,在编写传递命令行参数的代码时要注意使argv[argc]的值为NULL。

    因此,在遍历命令行参数的时候,处理的循环可以写成如下的形式:

    for (i = 0; argv[i] != NULL; i++)

    3 环境变量

    3.1 概述

    环境变量和命令行参数的情况有所不同。每个程序都会有一个环境变量表,和命令行参数表一样,环境变量表也是一个指针数组。

    extern char ** environ;

    每个环境变量的表示形式为:

    环境变量名=环境变量值(最后有一个‘’结束符)

    环境变量表就是由若干个这样的字符串组成的,最后由一个NULL指针作为结束标志。下面的实例演示了打印进程的环境变量,该程序顺序遍历环境变量表,并输出每一个环境变量值。

     1 //print environment argument table content 
     2 #include <stdio.h> 
     3 extern char ** environ;
     4 
     5 int main(int argc, char * argv[]) 
     6 { 
     7     int i; 
     8     for (i = 0; environ[i] != NULL; i++) 
     9         printf("[%d] : %s
    ", i, environ[i]); 
    10     return 0; 
    11 }
    main.c

    程序运行结果如下:

    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./app 
    [0] : XDG_VTNR=7 
    [1] : LC_PAPER=zh_CN.UTF-8 
    [2] : LC_ADDRESS=zh_CN.UTF-8 
    [3] : XDG_SESSION_ID=c1 
    [4] : XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/xiaomanon 
    [5] : SELINUX_INIT=YES 
    [6] : LC_MONETARY=zh_CN.UTF-8 
    [7] : CLUTTER_IM_MODULE=xim 
    [8] : GPG_AGENT_INFO=/run/user/1000/keyring-Lk6lyR/gpg:0:1 
    [9] : TERM=xterm 
    [10] : VTE_VERSION=3409 
    [11] : SHELL=/bin/bash 
    [12] : WINDOWID=60817420 
    [13] : LC_NUMERIC=zh_CN.UTF-8 
    [14] : UPSTART_SESSION=unix:abstract=/com/ubuntu/upstart-session/1000/1272 
    [15] : GNOME_KEYRING_CONTROL=/run/user/1000/keyring-Lk6lyR 
    [16] : GTK_MODULES=overlay-scrollbar:unity-gtk-module 
    [17] : USER=xiaomanon 
    [18] : LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36: 
    [19] : LC_TELEPHONE=zh_CN.UTF-8 
    [20] : XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0 
    [21] : XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0 
    [22] : SSH_AUTH_SOCK=/run/user/1000/keyring-Lk6lyR/ssh 
    [23] : DEFAULTS_PATH=/usr/share/gconf/ubuntu.default.path 
    [24] : XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg 
    [25] : DESKTOP_SESSION=ubuntu 
    [26] : PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games 
    [27] : QT_IM_MODULE=ibus 
    [28] : QT_QPA_PLATFORMTHEME=appmenu-qt5 
    [29] : LC_IDENTIFICATION=zh_CN.UTF-8 
    [30] : PWD=/home/xiaomanon/Documents/c_code 
    [31] : JOB=gnome-session 
    [32] : XMODIFIERS=@im=ibus 
    [33] : LANG=en_US.UTF-8 
    [34] : GDM_LANG=en_US 
    [35] : MANDATORY_PATH=/usr/share/gconf/ubuntu.mandatory.path 
    [36] : LC_MEASUREMENT=zh_CN.UTF-8 
    [37] : UBUNTU_MENUPROXY=1 
    [38] : COMPIZ_CONFIG_PROFILE=ubuntu 
    [39] : IM_CONFIG_PHASE=1 
    [40] : GDMSESSION=ubuntu 
    [41] : SESSIONTYPE=gnome-session 
    [42] : SHLVL=1 
    [43] : HOME=/home/xiaomanon 
    [44] : XDG_SEAT=seat0 
    [45] : LANGUAGE=en_US 
    [46] : GNOME_DESKTOP_SESSION_ID=this-is-deprecated 
    [47] : UPSTART_INSTANCE= 
    [48] : UPSTART_EVENTS=started starting 
    [49] : LOGNAME=xiaomanon 
    [50] : DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-vaiuLPOEru 
    [51] : XDG_DATA_DIRS=/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/ 
    [52] : QT4_IM_MODULE=xim 
    [53] : LESSOPEN=| /usr/bin/lesspipe %s 
    [54] : INSTANCE=Unity 
    [55] : TEXTDOMAIN=im-config 
    [56] : UPSTART_JOB=unity-settings-daemon 
    [57] : XDG_RUNTIME_DIR=/run/user/1000 
    [58] : DISPLAY=:0 
    [59] : XDG_CURRENT_DESKTOP=Unity 
    [60] : GTK_IM_MODULE=ibus 
    [61] : LESSCLOSE=/usr/bin/lesspipe %s %s 
    [62] : LC_TIME=zh_CN.UTF-8 
    [63] : TEXTDOMAINDIR=/usr/share/locale/ 
    [64] : LC_NAME=zh_CN.UTF-8 
    [65] : XAUTHORITY=/home/xiaomanon/.Xauthority 
    [66] : COLORTERM=gnome-terminal 
    [67] : _=./app 
    [68] : OLDPWD=/home/xiaomanon/Documents 
    View Code

        程序的运行结果是打印出很多的环境变量,这些环境变量是从调用exec()函数(即创建该进程的shell)中继承得来的。

        命令行参数需要由程序员手动编写代码传递给新的进程,而环境变量则不需要这样做。环境变量的获取是由操作系统自动完成的,在引用的时候只需要声明外部变量(extern char **environ)就可以了。环境变量和命令行参数的另一个不同点是命令行参数可以人为输入,而环境变量只能从调用exec()函数的进程那里继承而来,而且在本进程中修改环境变量不会影响到其他进程。

        修改命令行参数同样不会影响到其他进程,但是很少人去修改它,因为这样做是毫无意义可言的。

    3.2 获取指定的环境变量

        环境变量是一个字符指针数组,可以通过environ指针来访问其中的每一个元素,但是这种方式是不被推荐的。这里先介绍一种推荐的访问环境变量的方法,Linux环境下使用getenv()函数来得到一个环境变量,其函数原型如下:

    #include <stdlib.h>
    
    char* getenv(const char* name);

        getenv()函数的参数代表指定的环境变量的名称,该函数寻找一个形如“name=value”的字符串,然后将value字符串的内容作为环境变量的值返回。如果成功,getenv()函数返回该环境变量的字符串首地址;如果失败,则返回一个NULL指针。下面演示一个获取指定的环境变量的值,该程序调用getenv()函数得到指定的环境变量值,并将其输出。

     1 //print the specified environment table content 
     2 #include <stdio.h> 
     3 #include <stdlib.h>
     4 
     5 int main(int argc, char * argv[]) 
     6 { 
     7     char *p;
     8 
     9     p = getenv("PATH"); 
    10     if (p == NULL)//get environ failed 
    11     { 
    12         perror("fail to get environ
    "); 
    13         exit(-1); 
    14     } 
    15     printf("$PATH = %s
    ", p);
    16 
    17     return 0; 
    18 }
    main.c

    程序运行结果如下:

    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./app 
    $PATH = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games 

    3.3 设置环境变量

        Linux系统允许用户设置一个环境变量的值,当该环境变量已经有值时,还可以将其替换。如果添加的环境变量尚未存在与环境变量表中,系统会为用户添加这个环境变量。Linux环境下使用putenv()函数对一个环境变量赋值,其函数原型如下:

    #include <stdlib.h>
    
    int putenv(char *str);

        putenv()函数将一个形如“name=value”的字符串放进环境变量表,如果原来有值则替换掉原来的环境变量值。该函数也可以用来添加一个以前不存在的环境变量,如果成功对环境变量赋值,则函数返回0;如果修改失败,则返回-1.

     1 //set the specified environment table content 
     2 #include <stdio.h> 
     3 #include <stdlib.h>
     4 
     5 int main(int argc, char * argv[]) 
     6 { 
     7     char *p;
     8 
     9     //Get environ value 
    10     p = getenv("HOME"); 
    11     if (p == NULL)//get environ failed 
    12     { 
    13         perror("fail to get environ
    "); 
    14         exit(-1); 
    15     } 
    16     printf("$HOME = %s
    ", p); 
    17     //Set environ value 
    18     if (putenv("HOME=/home/test") != 0) 
    19     { 
    20         perror("fail to put environ
    "); 
    21         exit(-1); 
    22     } 
    23     p = getenv("HOME"); 
    24     if (p == NULL)//get environ failed 
    25     { 
    26         perror("fail to get environ
    "); 
    27         exit(-1); 
    28     } 
    29     printf("$HOME = %s
    ", p);
    30 
    31     //Set a non-exist environ value 
    32     if (putenv("NOEXIST=/tmp") != 0) 
    33     { 
    34         perror("fail to put environ
    "); 
    35         exit(-1); 
    36     } 
    37     p = getenv("NOEXIST"); 
    38     if (p == NULL)//get environ failed 
    39     { 
    40         perror("fail to get environ
    "); 
    41         exit(-1); 
    42     } 
    43     printf("$NOEXIST = %s
    ", p);
    44 
    45     return 0; 
    46 }
    main.c

    运行结果如下:

    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./app 
    $HOME = /home/xiaomanon 
    $HOME = /home/test 
    $NOEXIST = /tmp 

    补充:那么问题来了,要是想在原有环境变量值的基础上追加一条新的环境变量值,应该怎么做呢?

    也可以使用setenv()函数对环境变量进行赋值,其函数原型如下:

    #include <stdlib.h>
    
    int setenv(const char *name, const char *value, int rewrite);

        setenv()函数的第1个参数代表要进行赋值的环境变量的名称,第2个参数代表该环境变量的新值,第3个参数用于决定是否覆盖已经存在的环境变量的值。如果rewrite的值为0,则不修改原来的值;如果rewrite的值为非0,则修改原来的值。如果成功对环境变量赋值,则setenv()函数返回0;否则,返回-1。看下面的示例程序:

     1 //set the specified environment table content 
     2 #include <stdio.h> 
     3 #include <stdlib.h>
     4 
     5 int main(int argc, char * argv[]) 
     6 { 
     7     char *p;
     8 
     9     //Get environ value 
    10     p = getenv("HOME"); 
    11     if (p == NULL)//get environ failed 
    12     { 
    13         perror("fail to get environ
    "); 
    14         exit(-1); 
    15     } 
    16     printf("$HOME = %s
    ", p);
    17 
    18     //Set environ value, do not change orignal value 
    19     if (setenv("HOME", "/home/test", 0) != 0) 
    20     { 
    21         perror("fail to put environ
    "); 
    22         exit(-1); 
    23     } 
    24     p = getenv("HOME"); 
    25     if (p == NULL)//get environ failed 
    26     { 
    27         perror("fail to get environ
    "); 
    28         exit(-1); 
    29     } 
    30     printf("$HOME = %s
    ", p);
    31 
    32     //Set environ value, change orignal value 
    33     if (setenv("HOME", "/home/test", 1) != 0) 
    34     { 
    35         perror("fail to put environ
    "); 
    36         exit(-1); 
    37     } 
    38     p = getenv("HOME"); 
    39     if (p == NULL)//get environ failed 
    40     { 
    41         perror("fail to get environ
    "); 
    42         exit(-1); 
    43     } 
    44     printf("$HOME = %s
    ", p);
    45 
    46     return 0; 
    47 }
    main.c

    程序运行效果如下:

    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./app 
    $HOME = /home/xiaomanon 
    $HOME = /home/xiaomanon 
    $HOME = /home/test 

    3.4 删除环境变量

    Linux环境下使用unsetenv()函数删除一个环境变量的值,其函数原型如下:

    #include <stdlib.h>
    
    int unsetenv(const char *name);

    参数name表示要删除的环境变量名称,即使name所代表 的环境变量并不存在也不会出错。如果成功删除环境变量的值,函数的返回值为0;否则,返回-1。

    下面的示例以删除一个环境变量的值。

     1 //set the specified environment table content 
     2 #include <stdio.h> 
     3 #include <stdlib.h>
     4 
     5 int main(int argc, char * argv[]) 
     6 { 
     7     char *p;
     8 
     9     //Get environ value 
    10     p = getenv("HOME"); 
    11     if (p == NULL)//get environ failed 
    12     { 
    13         perror("fail to get environ
    "); 
    14         exit(-1); 
    15     } 
    16     printf("$HOME = %s
    ", p);
    17 
    18     //Delete environ value 
    19     if (unsetenv("HOME") != 0) 
    20     { 
    21         perror("fail to put environ
    "); 
    22         exit(-1); 
    23     } 
    24     p = getenv("HOME"); 
    25     if (p == NULL)//get environ failed 
    26     { 
    27         perror("fail to get environ
    "); 
    28         exit(EXIT_FAILURE); 
    29     } 
    30     printf("$HOME = %s
    ", p);
    31 
    32     return 0; 
    33 }
    main.c

    程序运行结果如下:

    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./app 
    $HOME = /home/xiaomanon 
    fail to get environ 
    : Success

    Linux下使用clearenv()函数清除所有环境变量表中的变量,其函数原型如下:

    #include <stdlib.h>
    
    int clearenv();

    clearenv()函数将环境变量连同值一起删除,而且连environ这个全局变量指针都会设置为NULL,撤销整个环境变量表。由此可见,对于此函数应该慎用。如果成功删除所有环境变量,函数返回0;否则,返回-1。


    4 进程结束状态

    4.1 得到进程结束状态

    Linux程序员可以通过shell得到已结束进程的结束状态。

    echo $?

    $?是Linux shell中的一个内置变量,其中保存的是最近一次运行的进程的返回值。这个返回值有一下3种情况:

    (1) 程序中的main函数运行结束,$?中保存main函数的返回值。

    (2) 程序运行中调用exit函数结束运行,$?中保存exit函数的参数。

    (3) 程序异常退出,$?中保存异常出错的错误号。

    下面的程序用来测试程序的结束状态,该程序接收整型输入,如果输入数字0则正常退出。

     1 #include <stdio.h>
     2 
     3 int main() 
     4 { 
     5     int i; 
     6     while (1) 
     7     { 
     8         scanf("%d", &i); 
     9         if (i == 0) 
    10             break; 
    11     } 
    12     return 14; 
    13 }
    hello.c

    程序运行效果如下:

    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./hello 
    12 
    0 
    xiaomanon@xiaomanon-machine:~/Documents/c_code$ echo $? 
    14 
    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./hello 
    ^C  (Ctrl+C) 
    xiaomanon@xiaomanon-machine:~/Documents/c_code$ echo $? 
    130 

    注意:首先,shell内置变量$?保存的是最近一次运行的进程的返回值,所以使用时窑确保在打印需要的进程返回值前不要有其他的操作,同时应该避免后台进程的干扰。其次,在运行程序是,如果程序运行出错,比如shell找不到指定的进程,那么$?内置变量中的值是1.

        所以,在编写代码时如果没有出错,则不要使main函数的返回值为1;或者使用exit(1)这样的写法,以免引起不必要的混乱。

    4.2 使用errno调试程序

    调试一个程序往往有以下几种方法:

    (1) 使用调试器

    (2) 在程序中直接使用输出函数输出调试信息。

    (3) 查看标准出错文件。

    (4) 查看程序异常时所写的日志。

        在Linux环境下执行系统调用时会出现一些错误,仅仅通过检查这些系统调用的返回值是不够的,开发者往往需要更多更详细的信息。C语言提供了一个全局变量errno,很好地弥补了Linux系统调用返回值信息不足的缺点。大多数Linux系统调用在出错时都会操作此变量,将其设置为一个特定的值,输出这个变量的值开发者就可以知道系统调用失败的原因,从而正确的排除错误。

    说明:errno是一个整型变量,其定义在errno.c中,声明在errno.h中。

        因此,如果希望在程序中使用此变量,应该在代码之前加上“#include <errno.h>”。下面的示例演示了使用errno变量输出出错信息。该程序试图打开一个不存在的文件,打开文件失败后使用errno变量输出其出错的原因。

     1 #include <stdio.h> 
     2 #include <stdlib.h> 
     3 #include <fcntl.h> 
     4 #include <unistd.h> 
     5 #include <errno.h>
     6 
     7 int main(void) 
     8 { 
     9     int fd; 
    10     errno = 0;//clear errno
    11 
    12     fd = open("./nothing.txt", O_RDWR); 
    13     if (errno == 0) 
    14         printf("Open Sucess.
    "); 
    15     else{ 
    16         printf("Fail to open, errno is : %d
    ", errno); 
    17         exit(-1); 
    18     }
    19 
    20     close(fd); 
    21     return 0; 
    22 }
    err.c

    程序运行效果如下:

    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./err 
    Fail to open, errno is : 2 
    xiaomanon@xiaomanon-machine:~/Documents/c_code$ touch nothing.txt 
    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./err 
    Open Sucess. 

    注意:因为errno是一个全局变量,所以该程序中所有的系统调用都会修改它的值,为了不让上一次的错误值影响这一次的判断,在使用errno变量之前需要将它清零。

    4.3 输出出错的原因

        由于errno只是一个整型值,必须通过查表才能知道其真正代表的错误原因,这样的理解不够直观。针对该问题,Linux提供了两个函数可以方便地完成由错误号到错误文字描述的转换。第一个函数是strerror(),根据错误号返回错误的字符描述,函数原型如下:

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

    我们对上一个程序做如下修改:

     1 #include <stdio.h> 
     2 #include <stdlib.h> 
     3 #include <fcntl.h> 
     4 #include <unistd.h> 
     5 #include <errno.h> 
     6 #include <string.h>
     7 
     8 int main(void) 
     9 { 
    10     int fd; 
    11     errno = 0;//clear errno
    12 
    13     fd = open("./nothing.txt", O_RDWR); 
    14     if (errno == 0) 
    15         printf("Open Sucess.
    "); 
    16     else{ 
    17         printf("Fail to open, reason : %s
    ", strerror(errno)); 
    18         exit(-1); 
    19     }
    20 
    21     close(fd); 
    22     return 0; 
    23 }
    err.c

    程序运行结果如下:

    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./err 
    Fail to open, reason : No such file or directory 

    另一个函数是perror(),会根据全局变量errno和传入的字符串,打印一条出错信息,其函数原型如下:

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

        perror()函数表示要输出的字符串,系统自动将使用errno变量映射得到的错误文件描述的字符串链接在参数字符串的后面。该字符串不需要添加‘ ’,perror()函数会自动添加。因此,我们在上一个程序的基础上再做简单修改:

     1 #include <stdio.h> 
     2 #include <stdlib.h> 
     3 #include <fcntl.h> 
     4 #include <unistd.h> 
     5 #include <errno.h>
     6 
     7 int main(void) 
     8 { 
     9     int fd; 
    10     errno = 0;//clear errno
    11 
    12     fd = open("./nothing.txt", O_RDWR); 
    13     if (errno == 0) 
    14         printf("Open Sucess.
    "); 
    15     else{ 
    16         perror("fail to open"); 
    17         exit(-1); 
    18     } 
    19     close(fd); 
    20     return 0; 
    21 }
    err.c

    程序运行结果如下:

    xiaomanon@xiaomanon-machine:~/Documents/c_code$ ./err 
    fail to open: No such file or directory

      


    参考资料

    [1] 吴岳,Linux C程序设计大全,清华大学出版社

  • 相关阅读:
    浏览器
    背景图片设置
    用CSS画平行四边形
    git常用操作
    函数Function
    Object类型的创建和访问
    执行环境及作用域
    传值和传引用
    String类型
    HTML< legend >标签
  • 原文地址:https://www.cnblogs.com/xiaomanon/p/4193895.html
Copyright © 2011-2022 走看看