目录
进程替换
替换函数的含义
命令行参数
环境变量
PATH
进程替换
我们先看代码:
1 #include<stdio.h>
2 #include<unistd.h>
3 int main()
4 {
5 printf("process...begin!\n");
6
7 execl("/usr/bin/ls","ls","-a","-l",NULL);
8
9 printf("process...end!\n");
10 return 0;
11 }
运行结果:
通过运行结果,我们会发现:
printf("process...end!\n");并没有被执行;
这是为什么?
我们先来看一下exec函数:
还有一个:int execve(const char *path, char *const argv[], char *const envp[]);
exec函数其实就是替换函数,图像表示:
以上述代码为例:execl("/usr/bin/ls","ls","-a","-l",NULL);就是将磁盘中的有一段程序的代码和数据替换掉父进程在内存中的代码和数据;exec*执行完毕后,后续的代码不见了,是因为被exec*替换了,所以不会执行exec*后面的代码,简单来说:被替换后后面代码已经找不到了,自然不会被执行;
这个替换,本质就是这个程序被加载到内存了(exec*函数类似于一种Linux上的加载函数);
那我们非要让后面的代码可以执行,要怎么做呢?
很简单,父进程中exec*函数后的代码无法执行是因为exec*函数的替换,把后续代码给替代了,找不到后续代码;那我们让后续代码可以找到不就可以了?怎么让它可以找到-------->fork创建子进程,在子进程中执行exec*函数,这就是用的我们之前提到的写实拷贝(让子进程自己去替换,父进程的代码和数据不受影响);
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<stdlib.h>
4 int main()
5 {
6 printf("process...begin!\n");
7
8 pid_t id =fork();
9 if(id==0)
10 {
11 execl("/usr/bin/ls","ls","-a","-l",NULL);
12 exit(1);
13 }
14 //父进程
15 sleep(5);
16 printf("process...end!\n");
17 return 0;
18 }
这样父进程后续代码就可以被执行了;
原理是什么呢?
一开始,子进程完全的父进程的拷贝(页表指向是红色箭头),后面由于exec*函数替换,因为替换的不仅仅是数据,连代码也替换了,这时OS就是进行写时拷贝,把代码和数据都复制了一份(绿色和蓝色箭头的指向);父进程代码和数据仍然存在;
替换函数的含义
(1)int execl(const char *path, const char *arg, ...);
这个l指的是list 列表,path就是要执行程序的路径,arg:在命令行中怎么执行,这个就怎么写:
例如:ls -a ---->"ls","-a",即可;最后一个参数必须为NULL;
(2)int execv(const char *path, char *const argv[]);
这个v指的是vector,path是路径,argv:就是把命令放到argv里面;
例如:
(3)int execlp(const char *file, const char *arg, ...);
用户可以不传要执行文件的路径,但是要传文件名,直接告诉exec*函数,我要执行谁;
这里的p:查找这个程序,系统会在环境变量PATH进行查找;
例如:
(4)int execle(const char *path, const char *arg, ...,char *const envp[]);
这里的e:environment:环境变量; envp[]:整体替换所有的环境变量;
例如:
当然,除了可以替换系统命令,也可以替换我们自己写的程序:
先写一个程序:test.c,然后执行:
使用:
即可:
运行结果:
命令行参数
我们发现在main函数中可带参数,也可以不带参数;
带参数:
这个参数有什么用呢?
我们看下面的代码,将argv打印出来:
运行结果:
根据运行结果我们可以理解:命令行参数本质是交给我们程序的不同选型,用来定制不同的程序功能,命令中会携带很多选项;
例如:ls -a;
ls -l;等
环境变量
在Linux中,存在一些全局的设置,表明,告诉命令行解释器应该取哪些路径下去寻找可执行程序;
PATH
PATH:环境变量;
$PATH:打印环境变量内存;
系统中很多的配置,在登录Linux系统的时候,已经加载到bash进程中(内存);
我们发现ls命令:并不需要./,但是我们自己写的程序,比如myprocess,运行时却要./myprocess才可以运行,这是为什么?
我们只需要将我们的程序配置到环境变量中即可;
那怎么配置呢?
/PATH=$PATH:路径;
例如:
PATH=$PATH:home/sxh/111/lesson06;
因为我们配置的这个PATH是在内存中,重启后,PATH就会复原;
当然,除了PATH,还有其他的环境变量,比如:HOME/SHELL/HISISIZE/PWD等;
env:查看所有环境变量
echo $xxx:查看某一个环境变量
export name=value:设置环境变量
unset name:取消环境变量
怎么打印环境变量?
运行结果:
注意:环境变量默认是可以被子进程拿到的;