shell就是运用程序替换的原理进行实现的。 何为程序替换? 假如操作系统正在执行某一个程序,然后我们利用程序替换函 数指定一个新的程序,让操作系统去执行我们新指定的程序。也就是这样一种情形下,我们fork一个进程,如果fork成功,子进程会和父进程执行相同的代码,而我们创建子进程是希望子进程执行指定的操作,所以需要执行exec族函数。 何为程序替换函数? 程序替换函数是一族函数,可以通过man命令进行查看。
实现步骤: 1)采用read函数读取标准输入写到显示器上的信息,并且返回读取到的字符个数,如果返回值大于0,说明有读取到字符,就将读到的字符串的最后加个字符串的结束符/0;否则,结束此次循环。 2)将读取到的字符串按照空格分成多个字符串,放进指针数组argv中,并在指针数组的最后加一个NULL。 3)创建一个子进程,父进程等待子进程执行完程序,子进程执行程序替换函数,关于程序替换函数的选择:我们选择的是execvp函数(因为我们已经知道要执行的程序的文件名,参数也已经全部存储在argv指针数组中)。 获得登录信息的关键函数: 1)getpwuid() 2)gethostname()
3)getcwd()函数
shell的基本功能: 1)自动获取用户名,主机名,当前目录; 2)可以实现连续按回车的情况; 3)按错命令可以有删除的功能(就是)。
//MyShell.c
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<ctype.h>#include<pwd.h>#include<string.h>void GetLoginName(){ struct passwd* pass; pass = getpwuid(getuid()); PRintf("[%s@",pass->pw_name);}void GetHostName(){ char name[128]; gethostname(name,sizeof(name)-1); printf("%s",name);}void GetDir(){ char pwd[128]; getcwd(pwd,sizeof(pwd)-1); int len = strlen(pwd); char* p = pwd+len-1; while(*p != '/' && len--) { p--; } p++; printf(" %s]@",p);}int main(){ while(1) { GetLoginName(); GetHostName(); GetDir(); fflush(stdout); //读取字符串 char buf[1024]; int s = read(0,buf,1024); if(s > 0)//有读取到字符 { int i = 0; for( i = 0; i < s; ++i) { if(buf[i] == '/b' && i >= 1) { // printf("debug:%d/n",i); int j = 0; for( j = i+1; j < s; ++j) { buf[j-2] = buf[j]; } buf[s-2] = 0; i-=1; } else if(buf[i] == '/b' && i == 0) { // printf("debug:%d/n",i); int j = 0; for( j = 1; j < s; ++j) { buf[j-1] = buf[j]; } buf[s-1] = 0; // i-=1; } else { continue; } } buf[s] = 0; } else { continue; } //将读取到的字符串分成多个字符串 char* start = buf; int i =1; char* MyArgv[10] = {0}; MyArgv[0] = start; while(*start) { if(isspace(*start)) { *start = 0; start++; MyArgv[i++] = start; } else { ++start; } } MyArgv[i-1] = NULL; //打印一下字符串信息 int m = 0; for(m = 0; m <i-1;++m) { printf("debug:%s/n",MyArgv[m]); } //fork新的进程 int id = fork(); if(id == 0) { //child,执行替换操作 execvp(MyArgv[0],MyArgv); perror("error"); exit(1); } else { printf("father/n"); wait(NULL); } } return 0;}//Makefile
MyShell:MyShell.c gcc -o MyShell MyShell.c.PHONY:cleanclean: rm -f MyShell新闻热点
疑难解答