UNIX再学习 -- 环境变量
之前讲gcc编译的时候,参看:C语言再学习 -- GCC编译过程 提到过静态库和共享库,那时只是简单的讲了下它们相关的编译链接,接下来就该详细介绍它们了。不过再讲解之前还需了解一下编程相关的环境变量。
一、环境变量
1、Windows下的环境变量
(1)环境变量配置
(2)常见环境变量:(了解)
2、Linux下的环境变量(重点)
修改和查看环境变量的指令
# echo $HOME
/root
(2)env:查看所有环境变量
# env
LC_PAPER=en_US.UTF-8
LC_ADDRESS=en_US.UTF-8
SSH_AGENT_PID=1768
LC_MONETARY=en_US.UTF-8
GPG_AGENT_INFO=/tmp/keyring-rB9csr/gpg:0:1
TERM=xterm
SHELL=/bin/bash
XDG_SESSION_COOKIE=619793d1806621208703bfca00000005-1489544306.787815-2133755939
WINDOWID=31457285
LC_NUMERIC=en_US.UTF-8
GNOME_KEYRING_CONTROL=/tmp/keyring-rB9csr
USER=root
.....
# env | grep SH
SSH_AGENT_PID=1768
SHELL=/bin/bash
SSH_AUTH_SOCK=/tmp/keyring-rB9csr/ssh
SHLVL=1
(3)set:查看本地定义的环境变量
root@ubuntu:~# set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:histappend:hostcomplete:interactive_comments:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="2" [2]="24" [3]="1" [4]="release" [5]="i686-pc-linux-gnu")
BASH_VERSION='4.2.24(1)-release'
.....
(4)export:设置一个新的环境变量 (临时的,重启后消失)
# export HELLO="hello"
# echo $HELLO
hello
(5)unset:清除环境变量
# unset HELLO
# echo $HELLO#
(6)readonly:设置只读环境变量
# export HELLO="hello"
# readonly HELLO="hello"
# export HELLO="hello" world
bash: HELLO: 只读变量
# unset HELLO
bash: unset: HELLO: 无法反设定: 只读 variable
Linux系统常用的环境变量
# echo $PATH
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/tarena/workdir/toolchains/opt/S5PV210-crosstools/4.4.6/bin
我们可以看到在当前目录下,默认的PATH的值。它表示当我们在当前目录下执行一条命令时命令的搜索路径。每一个目录都是以冒号隔开的。例如:export PATH=$PATH:/opt/arm-2009q1-203/bin:
# echo $HOME
/home/admin
# echo $HOME
/root
(3)HISTSIZE:保存历史命令记录的条数
# echo $HISTSIZE
1000
可以看到,上面显示能够保存1000条。
echo $LOGNAME
root
(5)HOSTNAME:显示主机的名字 (同 指令hostname)
echo $HOSTNAME
ubuntu
(6)SHELL:指当前用户使用的shell类型
echo $SHELL
/bin/bash
(7)LANG/LANGUGE:语言相关的环境变量,多语言可以修改此环境变量
echo $LANG
zh_CN.UTF-8
(8)MAIL:当前用户的邮件存放的目录 (无邮件)
# echo $MAIL
(9)PS1:命令基本提示符,对root是 #,对普通用户是 $
# echo $PS1
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\u@\h:\w\$
(10)PS2:附属提示符,默认是 >
# echo $PS2
>
存放环境变量的文件
gedit /etc/profile
添加 export PATH="/opt/hisi-linux/x86-arm/arm-hisiv300-linux/target/bin:$PATH"
执行 source /etc/profile
#gcc找到头文件的路径
$C_INCLUDE_PATH=/opt/example/include
$export C_INCLUDE_PATH #g++找到头文件的路径
$CPLUS_INCLUDE_PATH=/opt/example/include
$export CPLUS_INCLUDE_PATH #找到静态库的路径
$LIBRARY_PATH=/opt/example/lib
$export LIBRARY_PATH #找到动态链接库的路径
LD_LIBRARY_PATH=/opt/example/lib
export LD_LIBRARY_PATH
(4)~/.bashrc (单个用户)
gedit .bashrc
添加 export PATH=$PATH:/opt/arm-2009q1-203/bin:
执行 source .bashrc
3、编程相关的环境变量
下面摘取了两篇较权威的说明资料:
LIBRARY_PATH
The value of LIBRARY_PATH is a colon-separated list of directories, much like PATH.
When configured as a native compiler, GCC tries the directories thus specified when searching for special linker files, if it can't find them using GCC_EXEC_PREFIX.
Linking using GCC also uses these directories when searching for ordinary libraries for the -l option (but directories specified with -L come first).
2、 man7 上关于LD_LIBRARY_PATH的说明:
LD_LIBRARY_PATH
A colon-separated list of directories in which to search for
ELF libraries at execution-time. Similar to the PATH
environment variable. Ignored in set-user-ID and set-group-ID
programs.
后面发现 StackOverflow 上关于 LIBRARY_PATH 和 LD_LIBRARY_PATH 的解释更直白:
LIBRARY_PATH is used by gcc before compilation to search for directories containing libraries that need to be linked to your program.LD_LIBRARY_PATH is used by your program to search for directories containing the libraries after it has been successfully compiled and linked.EDIT: As pointed below, your libraries can be static or shared.
If it is static then the code is copied over into your program and you don't need to search for the library after your program is compiled and linked.
If your library is shared then it needs to be dynamically linked to your program and that's when LD_LIBRARY_PATH comes into play.
GCC编译、链接生成可执行文件时,共享库的搜索路径顺序如下(注意不会递归性地在其子目录下搜索):
1、gcc编译、链接命令中的-L选项;
2、gcc的环境变量的LIBRARY_PATH(多个路径用冒号分割);
3、gcc默认共享库目录:/lib:/usr/lib:usr/lib64:/usr/local/lib。
执行二进制文件时的共享库搜索路径
链接生成二进制可执行文件后,在运行程序加载共享库文件时,搜索的路径顺序如下:
1、编译目标代码时指定的共享库搜索路径:用选项 -Wl,rpath 和 include 指定的共享库的搜索路径,比如 gcc -Wl,-rpath,include -L. -ldltest hello.c,在执行文件时会搜索路径 `./include`;
2、环境变量LD_LIBRARY_PATH(多个路径用冒号分割);
3、在 /etc/ld.so.conf.d/ 目录下的配置文件指定的共享库绝对路径(通过ldconfig生效,一般是非root用户时使用);
4、gcc默认共享库目录:/lib:/usr/lib:usr/lib64:/usr/local/lib等。
其中,Linux GCC默认的共享库搜索路径可以通过 ld --verbose 命令查看:
SEARCH_DIR("/usr/i686-linux-gnu/lib32"); SEARCH_DIR("=/usr/local/lib32"); SEARCH_DIR("=/lib32"); SEARCH_DIR("=/usr/lib32"); SEARCH_DIR("=/usr/local/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib/i386-linux-gnu"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib/i386-linux-gnu"); SEARCH_DIR("=/usr/lib");
4、环境列表
//示例一
#include <stdio.h>int main(void)
{//声明全局变量extern char** environ;//给环境表首地址指定替身char** p = environ;while(*p != NULL){printf("%s\n",*p);//指向下一个p++;}return 0;
}功能等同指令env,可自行尝试
//示例二
#include <stdio.h>
#include <string.h>int main(void)
{//声明全局变量extern char** environ;//给环境表首地址指定替身char** p = environ;//练习:查找名字为SHELL的环境变量,获取SHELL的值存到buf的字符数组中,然后进行打印char buf[20] = {0};p = environ;while(*p != NULL){//比较前6个字符是否相等if(!strncmp(*p,"SHELL=",6)){//跳过环境变量名=strcpy(buf,*p+6);break;}//比较下一个p++;}printf("SHELL=%s\n",buf);return 0;
}
输出结果:
SHELL=/bin/bash功能等同指令echo $SHELL,可自行尝试
5、环境变量函数
#include <stdlib.h>
char *getenv (const char *name);
函数功能:
表示根据参数指定的环境变量名去环境表进行查找
#include <stdio.h>
#include <stdlib.h>int main (void)
{char *pc = getenv ("SHELL");if (NULL == pc)perror ("getenv"), exit (-1);printf ("SHELL = %s\n", pc);return 0;
}
输出结果:
SHELL = /bin/bash使用echo指令
# echo $SHELL
/bin/bash
(2)setenv函数
#include <stdlib.h>
int setenv (const char *name, const char *value, int overwrite);
第一个参数:环境变量名
第二个参数:环境变量值
第三个参数:是否修改
函数功能:
#include <stdio.h>
#include <stdlib.h>int main (void)
{char *pc = getenv ("SHELL");if (NULL == pc)perror ("getenv"), exit (-1);printf ("SHELL = %s\n", pc);setenv ("SHELL", "ABC", 1);printf ("修改后的SHELL = %s\n", getenv ("SHELL"));return 0;
}
输出结果:
SHELL = /bin/bash
修改后的SHELL = ABC
(3)putenv函数
#include <stdlib.h>
int putenv (char *string);
函数功能:
表示按照参数的内容增加/修改环境变量,其中string的格式为:name=value,如果不存在则添加,存在则删除
成功返回0,失败返回-1
#include <stdio.h>
#include <stdlib.h>int main (void)
{char *pc = getenv ("SHELL");if (NULL == pc)perror ("getenv"), exit (-1);printf ("SHELL = %s\n", pc);int res = putenv ("SHELL=abc");if (res)perror("putenv"),exit(-1);printf ("修改后的SHELL = %s\n", getenv ("SHELL"));putenv("CSDN=666");printf("增加的环境值是:%s\n",getenv("CSDN"));//123return 0;
}
输出结果:
SHELL = /bin/bash
修改后的SHELL = abc
增加的环境值是:666
(4)unsetenv函数
#include <stdlib.h>
int unsetenv (const char *name);
函数功能:
表示根据参数指定的环境变量去环境表中进行删除
成功返回0,失败返回-1
#include <stdio.h>
#include <stdlib.h>int main (void)
{putenv("CSDN=666");printf("增加的环境值是:%s\n",getenv("CSDN"));//123unsetenv("CSDN");printf("删除的结果是:%s\n",getenv("CSDN"));return 0;
}
输出结果:
增加的环境值是:666
删除的结果是:(null)
(5)clearenv函数
#include <stdlib.h>
int clearenv (void);
函数功能:
表示清空整个环境表
成功返回0,失败返回-1
#include <stdio.h>
#include <stdlib.h>int main (void)
{int res;putenv("CSDN=666");printf("增加的环境值是:%s\n",getenv("CSDN"));//123res = clearenv ();if(res)perror("clearenv"), exit(-1);printf("清空整个环境表结束\n");printf("CSDN = %s\n",getenv("CSDN"));return 0;
}
输出结果:
增加的环境值是:666
清空整个环境表结束
CSDN = (null)
6、主函数的原型
main函数原型:
int main (int argc, char * argv[], char * envp[]) {....}
第一个参数:命令行参数的个数
第二个参数:命令行参数的地址信息
第三个参数:环境表的首地址
参数argc表示输入参数的个数(含命令名),如果有命令行参数,argc应不小于1;argv表示传入的参数的字符串,是一个字符串数组,argv[0]表示命令名,argv[1]指向第一个命令行参数;至于第三个参数env,它与全局变量environ相比也没有带来更多益处,所以POSIX.1也规定应使用environ而不使用第三个参数。通常用getenv和putenv函数来存取特定的环境变量,而不是直接使用environ变量。例如:
//main函数原型的使用
#include <stdio.h>
int main(int argc,char* argv[],char* envp[])
{ printf("argc=%d\n",argc); int i=0; for(i=0;i<argc;i++) { printf("感谢%s\n",argv[i]); } //声明全局变量 extern char** environ; printf("environ=%p,envp=%p\n",environ,envp);//直接访问环境表 return 0;
}
输出结果为:
argc=1
感谢./a.out
environ=0xbfab74cc,envp=0xbfab74cc
UNIX再学习 -- 环境变量相关推荐
- UNIX再学习 -- exec 函数族
我们在讲,文件I/O的时候,简单提到过 exec 函数,讲到 vfork 的时候,也有用到.下面我们来详细介绍下它. 参看:UNIX再学习 -- 文件I/O 参看:UNIX再学习 -- 函数 for ...
- UNIX再学习 -- 内存管理
C 语言部分,就一再的讲内存管理,参看:C语言再学习 -- 再论内存管理 UNIX.Linux 部分还是要讲,足见其重要. 一.存储空间布局 1.我们先了解一个命令 size,继而引出我们今天要讲的 ...
- UNIX再学习 -- shell编程
UNIX环境高级编程看了三章,遇到不少重定向等shell命令.本想到Linux时再讲,看来有必要提前了.之前有看过一本<嵌入式Linux软硬件开发详解>这本书里有简单介绍了一部分shell ...
- UNIX再学习 -- 静态库与共享库
一.库 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.由于Windows和linux本质不同,因此二者库的二进制是不兼容的.库有两种:静态库(.a..lib)和共享库也称动态库 ...
- UNIX再学习 -- 线程
终于要讲到线程部分,线程和进程让人够头痛的内容. 一.线程概念 老样子,我们还是按我们讲进程时的方式说起,参看:UNIX再学习 -- 进程环境 首先需要了解下,什么是线程. Linux 下的线程,可能 ...
- UNIX再学习 -- exit 和 wait 系列函数
我们一开始讲进程环境时,就有提到了.进程有 8 种方式使进程终止. 其中 5 种为正常终止,它们是: (1)在 main 函数中执行 return (2)调用 exit 函数,并不处理文件描述符,多进 ...
- UNIX再学习 -- 进程间通信之管道
一.进程间通信概念 首先,需要了解一下什么是进程间通信. 进程之间的相互通信的技术,称为进程间通信(InterProcess Communication,IPC). 下图列出 4 种实现所支持的不同形 ...
- UNIX再学习 -- 进程关系
APUE 第 10 章信号讲完,回过头来看一下第 9 章的进程关系.终端登录和网络登录部分,我们只讲 Linux 系统的. 一.终端登录 我记得我们讲 root 登录设置时有提到,参看:C语言再学习 ...
- UNIX再学习 -- 信号
终于讲到信号部分,很多比较重要的应用程序都需处理信号.第 9 章需要先了解信号机制再看,所以先跳过不讲.现在开始详解信号. 一.信号概念 信号是提供异步事件处理机制的软件中断. 这些异步事件可能来自硬 ...
最新文章
- SCCM部署(四)---ADSI修改
- python大数据论坛_干货 | Python+大数据计算平台,PyODPS架构手把手教你搭建
- 【CyberSecurityLearning 78】DC系列之DC-9渗透测试
- mysql汉字占几个字符_mysql和oracle的一个汉字占几个字符
- matlab2015统计工具箱,matlab统计工具箱函数汇集
- TypeScript泛型详解
- 从零开始刷Leetcode——字符串(13.14.20.28)
- 每周荐书:SLAM、Vue2、爬虫(评论送书)
- always on sql 收缩日志_啥?我写的一条SQL让公司网站瘫痪了...
- IBus输入法安装和设置
- PPT幻灯片放映时不显示视频(旁白)
- kettle org.pentaho.ui.xul.XulException: java.lang.reflect.InvocationTargetException
- Nginx动静分离经典案例配置
- layui上传文件的choose只触发一次
- 微服务弹性伸缩与负载均衡
- [模板上新]病毒防疫主题公众号图文模板免费使用,武汉加油!
- 隔离电源与非隔离电源的选择及优缺点分析
- pip 和conda
- 免费的视频服务器空间
- 如何成为优秀的前端程序员?
热门文章
- delphi frame 添加 create onshow 事件
- 练习:利用函数实现一个登陆系统
- printf的使用和test的使用
- 前端编码规范,个人感觉bootstrap总结的不错,拿出来给大家分享
- nginx upstream setting
- dev控件中LookUpEdit的数据绑定问题
- IIS问题解决之——无法访问数据库
- 有关ucosii中OSTCBY、OSTCBBitY、OSTCBX、OSTCBBitX的意义(我是菜鸟)
- 基于小波变换的图像边缘检测(matlab祖传代码注释)
- [云炬python3玩转机器学习笔记] 3-1 Jupyter Notebook