Unix C:环境变量

环境变量

什么是环境变量

  • 每个进程都有一张自己的环境变量表,表中的每个条目都是形如键=值形式的环境变量
  • 进程可以通过环境变量访问计算机的资源
  • 在终端下输入env命令,可以查看环境变量列表
  • 通过echo $name可以查看某个环境变量的值

环境变量的添加

  • 在终端窗口输入FOOD=apple,表示向当前进程中增加名为FOOD值为apple的环境变量,如果环境变量已经存在,则更改其值。注意:在=左右不能有空格

环境变量的类别

  • 环境变量分为两大类:
    • 全局环境变量:当前shell和其子进程都是可见的
    • 局部环境变量:只有当前shell可见
  • 将局部环境变量设置全局变量:export name
  • 删除环境变量:unset name

常见环境变量

  • PATH环境变量
    • echo $PATH
    • 该环境变量所记录的是bash进程对命令的检索路径
    • 格式为:分割的多个路径。在bash下输入命令的时候,首先,在第一个路径下找该命令的可执行程序,找到就执行,找不到就到下一个路径继续找,重复直到找到位置,如果最后一个路径也没找到,就提示该不能找到该命令的错误提示
  • 对PATH环境变量进行设置,添加当前路径到环境变量
    • PATH=$PATH
    • 在命令执行程序即可省略./,例如./a.out= a.out
  • 如果没有特殊操作,对环境变量的设置尽对当前shell进程有效,开启新的终端中之前的操作不会保留
  • bash进程启动前都会执行用户家目录下.bashrc的脚本文件,将环境变量添加到.bashrc文件中就可以对每个bash进程有效
    • 执行source ~./bashrc命令即可立即生效

用户变量

~/.bashrc~/.bash_file,~表示这是用户目录下的,即里面的环境变量也叫shell变量,是局部的,只对特定的shell有效,用vim在用户目录下的.bash_profile文件中增加变量,变量仅会对当前用户有效,并且是永久的

要让刚才的修改马上生效,需要执行以下代码:

BASH
source ~/.bash_profile

~/.bashrc~/.bash_file两个的区别

.bash_profile只在会话开始时被读取一次,而.bashrc则每次打开新的终端时,都会被读取。

  • 当shell是交互式登录shell时,读取.bash_profile文件,如在系统启动、远程登录或使用su -切换用户时;
  • 当shell是交互式登录和非登录shell时都会读取.bashrc文件,如:在图形界面中打开新终端或使用su切换用户时,均属于非登录shell的情况。

全局变量

  • /etc/profile/etc/profile.d,前面的是文件,后面.d表示目录。
  • /etc/profile里面的变量是全局的,对所有用户的shell有效。
  • vim在文件/etc/profile文件中增加变量,该变量将会对Linux下所有用户有效,并且是永久的

要让刚才的修改马上生效,需要执行以下代码

source /etc/profile

环境变量表

所谓环境变量表就是一个以NULL指针结束的字符指针数组,其中每个元素都是一个字符指针,指向一个以空字符结尾的字符串,该字符串就是形如键=值形式的环境变量。该指针数组的地址保存在全局变量environ

通过全局变量表指针environ可以访问所有环境变量

extern char** environ;

char** pp;
for(pp = environ;*pp;++pp){
	printf("%s\n",*pp);
}

main函数的第三个参数

main函数的第三个参数就是环境变量表的起始地址

int main(int argc,char* argv[],char*envp[]){
    extern char** environ;
    printf("%p,%p\n",environ,envp);
    char**pp;
    for(pp=envp;*pp;p++){
        printf("%s\n",*pp);
    }
    return 0;
}

错误处理

  • 通过错误号了解具体的错误原因
  • 系统定义的整数类型全局变量errno中存储了最近依次系统调用的错误编号
  • 头文件errno.h中包含了对errno全局变量的外部声明和各种错误号的宏定义
/usr/include/errno.h
/usr/include/asm-generic/errno.h
/usr/include/asm-generic/errno-bash.h
#include<string.h>
char* strerror(int errnum)
  • 功能:将整数形式的错误号转换为有意义的字符串
  • 参数:errnum错误号
  • 返回值:返回与参数错误号对应的描述字符串
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>

int main(){
    int* p = malloc(0xffffffffffffffff);
	if(p == NULL){
		printf("errno = %d\n",errno);
		printf("malloc: %s\n",strerror(errno));
		return -1;
	}
	free(p);
	p = NULL;
	return 0;
}
/*输出结果:
cwork$./a.out 
errno = 12
malloc: Cannot allocate memory
*/

#include<stdio.h>

void perror(char const*tag);
  • 功能:在标准出错设备上打印最近依次函数调用的错误信息
  • 参数:tag 为用户自定义的提示内容,输出时会自动在该提示内容和错误信息直接添加冒号分隔
printf("errno = %d\n",errno);
printf("%s\n",strerror(errno));
perror("内存分配失败");
/*输出结果:
cwork$./a.out 
errno = 12
Cannot allocate memory
内存分配失败: Cannot allocate memory
*/
  • 注意

    • 虽然所有错误编号都不是0,但是因函数执行成功时存储错误编号的全局变量errno并不被清零,所以不能用该变量的值是否为零作为最近一次函数调用是否成功的判断条件
    • 正确做法是先更具函数的返回值判断是否出错,在确定出错的前提下,再根据errno的值判断具体出了什么错
    /*申请内存操作,这个地址太大会直接失败*/
    int* p = malloc(0xffffffffffffffff);
    /*打开文件操作,这里假定打开成功*/
    FILE* fp = fopen("text.txt");
    if(!errno){
        perror("fopen");
        return -1;
    }
    /*
    执行结果输出:
    fopen:Cannot allocate memory
    输出的错误是上一次申请内存失败的错误,说明不能使用errno的值来判断本次操作是否错误
    */
    /*正确的判断文件操作应该用fopen的返回值来判断
    fopen打开文件失败返回的指针为NULL:*/
    FILE* fp = fopen("text.txt");
    if(fp == NULL){
        perror("fopen");
        return -1;
    }
    

posted @ 2024-12-06 14:53  -O-n-e-  阅读(44)  评论(0)    收藏  举报