Linux environment variables and process address space
//View process pid and parent process [dy@VM-12-10-centos jincheng_12_5]$ ps ajx | head -1 && ps axj | grep 3669470 PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND 3669469 3669470 3669470 3669439 pts/0 3681645 S 1001 0:00 -bash 3669470 3681645 3681645 3669439 pts/0 3681645 R+ 1001 0:00 ps axj 3669470 3681646 3681645 3669439 pts/0 3681645 R+ 1001 0:00 grep --color=auto 3669470 //The first way to run a program without adding a path [dy@VM-12-10-centos jincheng_12_5]$ ll total 28 -rw-rw-r-- 1 dy dy 73 Dec 5 16:46 Makefile -rwxrwxr-x 1 dy dy 17432 Dec 5 16:47 proc -rw-rw-r-- 1 dy dy 75 Dec 5 16:47 proc.c [dy@VM-12-10-centos jincheng_12_5]$ sudo cp proc /usr/bin/ //Add your own executable program to the system path [sudo] password for dy: [dy@VM-12-10-centos jincheng_12_5]$ proc //Add your own executable program to the system path/ Path hello world! [dy@VM-12-10-centos jincheng_12_5]$ ./proc hello world! [dy@VM-12-10-centos jincheng_12_5]$ sudo rm /usr/bin/proc //Delete from system path [dy@VM-12-10-centos jincheng_12_5]$ proc -bash: /usr/bin/proc: No such file or directory //Second [dy@VM-12-10-centos jincheng_12_5]$ $PATH -bash: /home/dy/.local/bin:/home/dy/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin: No such file or directory [dy@VM-12-10-centos jincheng_12_5]$ pwd /home/dy/jincheng_12_5 //Add the current PATH to the environment variable PATH [dy@VM-12-10-centos jincheng_12_5]$ PATH=$PATH:/home/dy/jincheng_12_5 [dy@VM-12-10-centos jincheng_12_5]$ proc hello world! //Save only 3000 commands [dy@VM-12-10-centos jincheng_12_5]$ echo $HISTSIZE 3000 //Show how many commands before [dy@VM-12-10-centos jincheng_12_5]$ history |wc -l 636 [dy@VM-12-10-centos jincheng_12_5]$ history //Output all previous commands to the display //Show all environment variables [dy@VM-12-10-centos jincheng_12_5]$ env 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:mi=01;05;37;41: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:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=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:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=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:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.m4a=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.oga=01;36:*.opus=01;36:*.spx=01;36:*.xspf=01;36: LANG=en_US.utf8 HISTTIMEFORMAT=%F %T HOSTNAME=VM-12-10-centos OLDPWD=/home/dy USER=dy PWD=/home/dy/jincheng_12_5 HOME=/home/dy MAIL=/var/spool/mail/dy SHELL=/bin/bash TERM=xterm SHLVL=1 PROMPT_COMMAND=history -a; history -a; printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/\~}" LOGNAME=dy PATH=/home/dy/.local/bin:/home/dy/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dy/jincheng_12_5 HISTSIZE=3000 LESSOPEN=||/usr/bin/lesspipe.sh %s _=/usr/bin/env
-
echo: displays the value of an environment variable
-
export: set a new environment variable
[dy@VM-12-10-centos jincheng_12_5]$ ./proc //No local variables I am a proc : pid:3700079 ppid:3669470 Segmentation fault (core dumped) [dy@VM-12-10-centos jincheng_12_5]$ export MY_VAL [dy@VM-12-10-centos jincheng_12_5]$ ./proc I am a proc : pid:3700163 ppid:3669470 hello dy /home/dy/.local/bin:/home/dy/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dy/jincheng_12_5 /home/dy /bin/bash
-
env: show all environment variables
-
unset: clear environment variable
env environment variable
-
set: displays locally defined shell variables and environment variables
//Setting environment variables [dy@VM-12-10-centos jincheng_12_5]$ hello=1234 //Remember to add the $character to the output environment variable [dy@VM-12-10-centos jincheng_12_5]$ echo $hello 1234 [dy@VM-12-10-centos jincheng_12_5]$ set | grep hello hello=1234
The parent process of most instructions running on the command line is bash. Bash creates a child process, which executes your commands.
Get environment variables through code
#include<stdio.h> #include<stdlib.h> #include<unistd.h> int main(int argc, char *argv[], char *env[]) { for(int i = 0; argv[i]; ++i)//Explain command line parameters //for(int i = 0; i < argc; ++i) { printf("argv[%d]: %s\n",i,argv[i]); } for(int i = 0; env[i]; ++i)//Environment variables can be obtained through code { printf("env[%d]: %s\n",i,env[i]); } return 0; }
int x = atoi(argv[2]); int y = atoi(argv[3]); if(strcmp(argv[1],"-a") == 0) { printf("%d + %d = %d\n",x,y,x+y); } else { printf("%d - %d = %d\n",x,y,x-y); }
Each program will receive an environment table, which is an array of character pointers, and each pointer points to an environment string ending in '\ 0'
The environment can also be obtained through the third-party variable environ
#include <stdio.h> int main(int argc, char *argv[]) { extern char **environ; int i = 0; for(; environ[i]; i++){ printf("%s\n", environ[i]); } return 0; }
Process address space
#include<stdio.h> #include<unistd.h> int g_val = 0; int main() { pid_t id = fork(); if(id < 0) { perror("fork() fail\n"); } else if(id == 0) { printf("I am a child: %d,%d,%p\n",getpid(),g_val,&g_val); }else { printf("I am a fatcher: %d,%d,%p\n",getppid(),g_val,&g_val); } return 0; }
Through the running results, we can see that the value and address of the variables of the two processes are the same. There is no change to the code here. The child process takes the parent process as the template, so the address is the same.
Let's change the code a little
#include<stdio.h> #include<unistd.h> int g_val; int main() { pid_t id = fork(); if(id < 0) { perror("fork() fail"); } else if(id == 0) { g_val = 100; printf("I am a child: %d,%d,%p\n",getpid(),g_val,&g_val); }else { sleep(3); printf("I am a fatcher: %d,%d,%p\n",getppid(),g_val,&g_val); } return 0; }
At this time, we find that the value of the variable has changed. The parent process is 0 and the child process is 100, but the address of the variable is still the same.
Through this operation result, we can know the following points.
- The values of the variables of the two processes are different, so the variables of the parent and child processes are definitely not the same variable
- The address value is the same, definitely not a physical address!!!
- All the addresses we see are virtual addresses!!! The real physical address is invisible to the user and is uniformly managed by the OS (the OS is responsible for the virtual address – physical address)
- The code is shared, and the data is private (copy on write)
About why virtual addresses, not physical addresses?
What is the process address space?
- Process address space: it is a concept abstracted from the way of looking at memory, kernel struct mm struct. Each process thinks that it monopolizes the system memory resources (you think your father's property is yours alone)
- Region division: the address space is linear and is divided into regions one by one, [start,end]
- Virtual address: addresses between [start, end] are called virtual addresses
A mapping from a virtual address to a physical address
Why is there a process address space?
- Protect the physical memory and do not receive direct access to the address in any process, which is convenient for legitimacy verification
- Decouple memory management from process management
- Let each process look at the code and data in the same way
Later, we can directly tell the difference between process and program.
It's not easy to update, remember the third consecutive!!!