目录
补充知识
补充知识:编译完程序之后,变量名,函数名已经不存在了,被变成了地址(虚拟地址)。
扫描二维码关注公众号,回复: 14553042 查看本文章测试能跑多少子进程
shell执行的命令通常有俩种
1.第三方(除过用户和系统本身)提供的对应的在磁盘中有具体二进制文件的可执行程序
2.shell内部,自己实现的方法,由自己(父进程)来执行,如cd,这些命令会影响shell本身
将环境变量导到自己写的shell
我们直到export是添加环境变量。
我们对我们写的shell稍作修改,我们的目的是不覆盖父进程的环境变量,只给我们自己的shell新增环境变量
putenv
int putenv(const char * string);
功能:
putenv()用来改变或增加环境变量的内容。参数string的格式为name=value,如果该环境变量原先存在,则变量内容会依参数string改变,否则此参数内容会成为新的环境变量。
返回值:
执行成功则返回0,有错误发生则返回-1。
错误代码:
ENOMEM 内存不足,无法配置新的环境变量空间。
利用putenv把环境变量导入到我们的shell中新增环境变量的程序
导入了环境变量,但是此时exit=0,说明导入失败了
这是因为我们把完整的子字符串保存在了cmd__line中,打散后的字符串保存在了g_garp中,每次添加环境变量的时候不是把环境变量对应的字符串拷贝到指针数组对应的空间中,而是把字符串的地址添加到指针数组当中,虽然我们切割了子串,但是子串的内容还是保留在了cmd_line中,而g_argv其实是保存了切割后的子串的地址,当我们下一次执行循环的时候,环境变量被清空,环境变量的地址可能没变,但是cmd_line已经被清空,所以下次再打的时候就成了NULL。
新创建一个指针数组,这是为了不让环境变量和cmd_line共用空间,整体拷到一个全新空间里,防止下一次被覆盖
在子进程中新增打印的语句
mytest.c
完整代码
shell.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#define NUM 1024
#define SIZE 32
#define EP " "
char cmd_line[NUM];//保存完整的字符串
char* g_garp[SIZE];//保存打散后的字符串
char g_myval[64];
int main()
{
while (1)
{
printf("[root@localhost myshell]# ");
fflush(stdout);
memset(cmd_line, '\0', sizeof cmd_line);
if (fgets(cmd_line, sizeof cmd_line, stdin) == NULL)
{
continue;
}
cmd_line[strlen(cmd_line) - 1] = '\0';
g_garp[0] = strtok(cmd_line, EP);
int index = 1;//作为打散后要保存字符串的下标
if (strcmp(g_garp[0], "ls") == 0)
{
g_garp[index++] = "--color=auto";
}
if (strcmp(g_garp[0], "ll") == 0)
{
g_garp[0] = "ls";
g_garp[index++] = "-l";
g_garp[index++] = "--color=auto";
}
while (g_garp[index++] = strtok(NULL, EP));
if (strcmp(g_garp[0], "export") == 0 && g_garp[1] != NULL)
{
strcpy(g_myval, g_garp[1]);
int ret = putenv(g_myval);
if (ret == 0)
printf("%s export success\n", g_garp[1]);
continue;
}
if (strcmp(g_garp[0], "cd") == 0)
{
if (g_garp[1] != NULL);
chdir(g_garp[1]);
continue;
}
pid_t id = fork();
if (id == 0)
{
printf("下面子进程要进行的是\n");
printf("child MYVAL:%s\n", getenv("MYVAL"));
printf("child PATH:%s\n", getenv("PATH"));
execvp(g_garp[0], g_garp);
exit(0);
}
//父进程获取子进程信息
int status = 0;
pid_t ret = waitpid(id, &status, 0);
if (ret > 0)
printf("exit code:%d\n", WEXITSTATUS(status));
}
return 0;
}
mytest.c
#include<stdio.h>
#include<stdlib.h>
int main()
{
printf("HELLO WORLD\n");
printf("myenv:%s\n", getenv("MYVAL"));
return 0;
}
shell环境变量的来源
环境变量是写在配置文件中的,当shell启动的时候,通过读取配置文件获得的起始环境变量