我们知道,shell执行的命令,通常有两种:
1:第三方提供对应的在磁盘中有具体二进制的可执行程序**(由子进程执行)。**
2:shell命令中,自己实现相关方法等,因为对于有些影响shell本身的命令通常由父进程执行,我们通常称之为内置命令。例如 :cd命令,export命令等。
一般而言,用户通过shell命令由父进程通过export命令传递给命令行参数数组后通过判断调用getenv()函数接口,将存放在缓冲区里面的环境变量内容地址导入到当前shell的环境变量中。进而创建一个环境变量后再进行重新输入命令行参数,进行对代码的解析,创建子进程等。

但是当我们使用export命令调用系统接口命令,当子进程执行进程替换去调用父进程时,子进程执行的新程序去并没有获取到由父进程继承的环境变量。

运行结果如下:
获取到的环境变量为null.

我们怀疑是因为用户在使用export 增加环境变量时,调用系统接口产生错误,导致环境变量没有导入到当前shell中。
所以我们决定在调用系统接口putenv函数后,打印查看当前shell的环境变量。

运行结果如下:
我们成功将环境变量myval导入到当前shell的环境变量中。

那么,既然在导入环境变量后,当前shell已经有了需要的环境变量,那么为什么子进程执行test.c获取环境变量时却获取不到呢?
所以我们怀疑是子进程在进行进程替换后执行新程序时发生了问题。所以,我们要排除该因素。
我们决定,在子进程执行进程替换前便读取父进程导入的环境变量。

运行结果如下:
在执行进程替换前,依旧无法获取由子进程继承自父进程的环境。

那么有没有可能子进程不能获取环境变量所导致的呢?
为了应对这一问题,我们在进程替换前求取系统默认的环境命令PATH,测试它是否能够求出来。
运行结果如下:
在子进程中依旧能够获取到系统默认的环境变量PATH。

小总结:
经由上述操作,我们既排除了父进程调用系统命令putenv函数调用失败的问题,也排除了子进程执行进程替换后的因素和子进程是否能获取环境变量等问题。问题范围一步步减小。
此时,针对于这种情况,那就最有可能是函数所传的参数有问题。
我们知道putenv函数实际上是将储存在cmd_line缓冲的环境变量的地址导入当前shell的命令行参数数组中。但是有可能在export导入环境变量时,子进程在执行新的程序时,父进程又将cmd_line缓冲区的进行初始化为’\0’了,所以当我们再使用getenv获取字符串时,通过当前环境变量的地址找到cmd_line缓冲区的值为’\0’。所以我们获取的环境 变量的值可能就为null了。
针对这一情况,我们就不能再让子进程执行新程序时让父进程初始化cmd_line缓冲区了。所以我们可以尝试将cmd_line缓冲区的内容再重新拷贝一份。

运行结果如下:
此时获取环境变量可执行程序test成功获取到环境变量内容。

总结:
在进行程序排错时,我们要不断去逐一排查一段程序有可能出现的问题,通过控制变量的方法不断缩小所要查找的范围。最后确定该问题后从该问题所关联的代码中查找。
通过上诉论述及其配合我们知道的有关知识,比如minishell中子进程执行进程替换会将父基础的代码和数据替换,可是存储在父进程缓冲区里面的环境变量有关数据并没有被替换掉。
这是属于进程替换的一种特殊情况,我们可以理解成在执行进程替换的时候,并不是将父所有的数据和代码都替换掉,对于系统有关的环境变量与数据并不需要新程序替换。这也体现出环境变量具有全局属性。
