实现一个模拟的Shell
实验内容:
实现一个模拟shell:编写三个不同的程序:cmd1.c, cmd2.c, cmd3.c,每个程序输出一句话(或者任何自己想实现的功能),分别编译成可执行文件cmd1, cmd2, cmd3。然后再编写一个程序,模拟shell程序的功能,能根据用户输入的字符串(表示相应的命令名),去为相应的命令创建子进程并让它去执行相应的程序,而父进程则等待子进程的结束,然后再等待接收下一条命令。如果接收到的命令为exit,则父进程结束,如果接收到无效命令,则显示”command not found”,继续等待。
平台:Ubuntu-Linux
这里给出三个例程文件:
cmd1.c/cmd2.c/cmd3.c(同格式,只需改中间的数字即可)
#include<stdio.h>
int main()
{
printf("this is cmd1,c!\n");
return 0;
}
将三个文件放在同一个文件夹下,并在这个文件夹里编写模拟shell
这里命名为Myshell.c
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void childprocess(int num,char * const argv[],char ** environ){
pid_t pid=fork();
if(pid<0)
printf("Child process failed!\n");
else if(pid==0){
switch(num){
case 1:execve("cmd1",argv,environ);
case 2:execve("cmd2",argv,environ);
case 3:execve("cmd3",argv,environ);
default:printf("process STOP!");
}
}
}
int main(int argc,char * const argv[], char **environ){
char a[10];
while(1){
fgets(a,10,stdin);
if (strcmp(a,"exit\n")==0) break;
else if (strcmp(a,"cmd1\n")==0){
childprocess(1,argv,environ);
}
else if (strcmp(a,"cmd2\n")==0){
childprocess(2,argv,environ);
}
else if (strcmp(a,"cmd3\n")==0){
childprocess(3,argv,environ);
}
else printf("Command not found\n");
}
}
childprocess
fork()函数
创建子进程,pid_t pid = fork();
成功:父进程返回子进程id,子进程返回0;
失败:父进程返回-1,子进程不会被创建;
execve()函数
定义:int execve(const char * filename,char * const argv[ ],char * const envp[ ]);
函数说明:execve()用来执行参数filename字符串所代表的文件路径,第二个参数是利用指针数组来传递给执行文件,并且需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组。
返回值:如果执行成功则函数不会返回,执行失败则直接返回-1,失败原因存于errno 中。
参数:
argv[]为保存命令行参数的字符串指针,其中第0个参数是程序的全名,以后的参数为命令行后面跟的用户输入的参数,argv参数是字符串指针数组,其各元素值为命令行中各字符串(参数均按字符串处理)的首地址。 指针数组的长度即为参数个数argc。数组元素初值由系统自动赋予。
也就是说,argv[i]是指向char类型的指针数组,指向char类型的i的首地址。而*char[i]就是指i这个字符串类型的内容
例:
./text.c sdshfjd/ 2 6 9 10
此时argc=6
argv[1]指向“sdshfjd/”
argv[2]指向“2”
argv[3]指向“6”
argv[4]指向“9”
argv[5]指向“10”
函数所传入参数中environ为环境表,是一个字符指针数组。num则是命令参数个数
main函数
fgets()
参数:
s: 字符型指针,指向存储读入数据的缓冲区的地址。
n: 从流中读入n-1个字符
stream : 指向读取的流。//stdin输入流
返回值:
1. 当n<=0 时返回NULL,即空指针。
2. 当n=1 时,返回空串"".
3. 如果读入成功,则返回缓冲区的地址。
4. 如果读入错误或遇到文件结尾(EOF),则返回NULL.
编写Makefile文件