网站建设分析徐州整站优化
news/
2025/9/26 18:02:16/
文章来源:
网站建设分析,徐州整站优化,云计算培训,做音箱木工网站shell的模拟实现
我们知道shell是一个永不退出的程序#xff0c;所以他应该是一个死循环#xff0c;并且shell为了防止影响到自己#xff0c;我们在命令行上输入的所有命令都是由shell的子进程来执行的#xff0c;所以它应该要有创建子进程的相关函数#xff0c;当然也会…shell的模拟实现
我们知道shell是一个永不退出的程序所以他应该是一个死循环并且shell为了防止影响到自己我们在命令行上输入的所有命令都是由shell的子进程来执行的所以它应该要有创建子进程的相关函数当然也会有进程替换的相关函数因为我们直接创建子进程父子进程是共享代码的如果没有进程替换shell根本无法让子进程执行特定的命令。 总的思路 1.打印提示符 获取用户命令字符串 2.分割字符串 //“ls -a -l” — “ls” “-a” “-l” 3.check buildin command 检查内键命令 4.执行命令 1.打印提示符 获取用户命令字符串 对于getUserCommand函数 先介绍fgets函数 #define NUM 1024
#define SIZE 64int getUserCommand(char *command,int num)
{printf([%s%s %s],getUsername(),getHostname(),getCwd());//不用scanf遇到空格会停不好用char *r fgets(command,num,stdin);//最终还是会输入\nif(r NULL) return -1;//abcd\ncommand[strlen(command) - 1] \0;//给最后加上\0return strlen(command);
}getUsername(),getHostname(),getCwd() 是为了读取用户名主机名 当前所在文件夹 2.分割字符串
比如我要执行ls命令ls命令后还可以携带选项ls -a -lshell需要获取指令与选项并将它们分割shell接收到的是一串字符串ls -a -lshell需要将字符串分割为更小的字符串ls “-a” “-l”。
定义char usercommand[NUM];接收一整行的指令该数组中的元素保存的是字符char *argv[SIZE];//存储命令拆分后结果该数组中的元素要保存的是分割后的字符串。 介绍strtok void commandSplit(char *in,char *out[])
{int argc 0;out[argc] strtok(in, );//分隔并放入out指针数组while(out[argc] strtok(NULL, ));
}3.check buildin command 检查内键命令 内建命令
开头说到shell的命令分为内部命令和其他命令何为内建命令 内建命令是一个需要shell自己执行的命令即shell不创建子进程自己亲自执行的命令。
shell对于一些命令是必须要亲自执行的比如cd更改工作路径将shell的工作路径修改后由于子进程的工作路径与父进程相同更改分进程的工作路径后父进程创建出的子进程的工作路径也是被修改过的体现给用户的感觉就是当前的工作路径改变了。
对于内建命令shell是怎么实现的 shell中有许多内建命令当shell接收到指令并解析后需要判断用户输入的命令是否为内建命令如果是就执行拦截操作使子进程不再被创建自己执行该指令。如果不是内建命令则创建子进程执行该命令。 内建命令太多代码里面只写了cd和export内建命令。 char cwd[1024];//全局变量
char enval[1024];//for test char *homepath()
{char *home getenv(HOME);if(home) return home;else return (char*).;
}void cd(const char *path)
{chdir(path);//chdir(),用户将当前的工作目录改变成以参数路径所指的目录char tmp[1024];getcwd(tmp,sizeof(tmp));//getcwd()会将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数size为buf的空间大小。sprintf(cwd,PWD%s,tmp); //打印到字符串中putenv(cwd);//putenv 函数会将cwd 直接填写到环境表中
}// 什么叫做内键命令: 内建命令就是bash自己执行的类似于自己内部的一个函数
// 1-yes, 0-no, -1-err
int doBuildin(char* argv[])
{if(strcmp(argv[0],cd) 0) //cd ...{char *path NULL;if(argv[1] NULL) path homepath();//纯cd回到HOMEelse path argv[1];cd(path);//进入要进入的路径return 1;}else if(strcmp(argv[0],export) 0){if(argv[1] NULL) return 1;strcpy(enval,argv[1]);//拷贝putenv(enval);//直接填写到环境表中return 1;}return 0;
}对于void cd(const char *path)用 chdir() 函数来将 用户当前的工作目录改变成以参数路径所指的目录 用 getcwd() 函数将当前工作目录的绝对路径复制到参数buffer所指的内存空间中 用 sprintf() 函数将 “PWD工作目录” 字符串打印给cwd 用putenv 将cwd 直接填写到环境表中。
4.执行命令 int execute(char *argv[])
{pid_t id fork();if(id 0) return -1;else if(id 0) //child{//exec commandexecvp(argv[0],argv);//execvp()会从环境变量所指的目录中查找符合参数 file 的文件名, 找到后执行该文件, 然后将第二个参数argv 传给该执行的文件。exit(1);}else //father{int status 0;pid_t res waitpid(-1, status, 0);//阻塞式等待if(res 0)//等待成功{printf(exit code: %d \n, WEXITSTATUS(status));}}return 0;
}用子进程进行进程替换执行命令
在进行进程替换时使用ececvp()函数
效果动态图 代码
#includestdio.h
#includestdlib.h
#includestring.h
#includeunistd.h
#includesys/types.h
#includesys/wait.h#define NUM 1024
#define SIZE 64char cwd[1024];
char enval[1024];//for test char *homepath()
{char *home getenv(HOME);if(home) return home;else return (char*).;
}const char *getUsername()
{const char *name getenv(USER);if(name) return name;else return none;
}const char *getHostname()
{const char *hostname getenv(HOSTNAME);if(hostname) return hostname;else return none;
}const char *getCwd()
{const char *cwd getenv(PWD);if(cwd) return cwd;else return none;
}int getUserCommand(char *command,int num)
{printf([%s%s %s],getUsername(),getHostname(),getCwd());//不用scanf遇到空格会停不好用char *r fgets(command,num,stdin);//最终还是会输入\nif(r NULL) return -1;//abcd\ncommand[strlen(command) - 1] \0;return strlen(command);
}void commandSplit(char *in,char *out[])
{int argc 0;out[argc] strtok(in, );//分隔并放入out指针数组while(out[argc] strtok(NULL, ));
}void cd(const char *path)
{chdir(path);//chdir(),用户将当前的工作目录改变成以参数路径所指的目录char tmp[1024];getcwd(tmp,sizeof(tmp));//getcwd()会将当前工作目录的绝对路径复制到参数buffer所指的内存空间中,参数size为buf的空间大小。sprintf(cwd,PWD%s,tmp); //打印到字符串中putenv(cwd);//putenv 函数会将c wd 直接填写到环境表中
}// 什么叫做内键命令: 内建命令就是bash自己执行的类似于自己内部的一个函数
// 1-yes, 0-no, -1-err
int doBuildin(char* argv[])
{if(strcmp(argv[0],cd) 0) //cd ...{char *path NULL;if(argv[1] NULL) path homepath();else path argv[1];cd(path);return 1;}else if(strcmp(argv[0],export) 0){if(argv[1] NULL) return 1;strcpy(enval,argv[1]);putenv(enval);return 1;}return 0;
}int execute(char *argv[])
{pid_t id fork();if(id 0) return -1;else if(id 0) //child{//exec commandexecvp(argv[0],argv);//execvp()会从环境变量所指的目录中查找符合参数 file 的文件名, 找到后执行该文件, 然后将第二个参数argv 传给该执行的文件。exit(1);}else //father{int status 0;pid_t res waitpid(-1, status, 0);//阻塞式等待if(res 0)//等待成功{printf(exit code: %d \n, WEXITSTATUS(status));}}return 0;
}int main()
{while(1){char usercommand[NUM];//存储命令char *argv[SIZE];//存储命令拆分后结果//1.打印提示符 获取用户命令字符串int n getUserCommand(usercommand,sizeof(usercommand));if(n 0) continue;//输入空也可以重新输入//2.分割字符串//ls -a -l --- ls -a -lcommandSplit(usercommand,argv);//3.check buildin command 检查内键命令n doBuildin(argv);if(n) continue;//4.执行命令execute(argv);}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/916955.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!