操作系统课程设计(三)
1、实现一个模拟shell:编写三个不同的程序:cmd1.c, cmd2.c, cmd3.c,每个程序输出一句话,分别编译成可执行文件cmd1, cmd2, cmd3。然后再编写一个程序,模拟shell程序的功能,能根据用户输入的字符串(表示相应的命令名),去为相应的命令创建子进程并让它去执行相应的程序,而父进程则等待子进程的结束,然后再等待接收下一条命令。如果接收到的命令为exit,则父进程结束,如果接收到无效命令,则显示”command not found”,继续等待。
exec函数
进程exec系列函数
fork和exec
fork详解
shell中exec函数详解ll中
fork执行过程
//myshell.c
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#define CMD_COLLECTION_LEN 4 //命令数组的长度(有4命令)
//命令索引
#define INVALID_COMMAND -1 //无效命令返回-1
#define EXIT 0
#define CMD_1 1
#define CMD_2 2
#define CMD_3 3
//bool
#define TRUE 1
char *cmdStr [CMD_COLLECTION_LEN ]= {"exit","cmd1","cmd2","cmd3"};
//对比所有命令参数,如果有一样的,就返回对应数字,用于后面执行
int getCmdIndex(char *cmd)
{
int i;
for(i=0;i<CMD_COLLECTION_LEN;i++)
{
if (strcmp(cmd,cmdStr[i])==0)
{
return i;
}
}
return -1;
}
/*
Linux系统中执行新任务的方法是先调用fork()创建一个子进程,
接着调用exec()读取指定可执行文件并载入该子进程的地址空间运行,
这也是shell的典型用法
*/
/*
创建子进程,这里使用了execl,后面的l表示list,即参数列表。
第一参数为path(要执行的文件路径),最后一个参数必须是NULL,
中间的为要传送的参数
*/
void myFork(int cmdIndex)
{
pid_t pid;
if((pid = fork())<0)
{
printf("创建子进程错误\n");
exit(0);
}
else if (pid == 0)
{
int execl_status = -1;
printf("子进程正在运行\n");
switch(cmdIndex)
{
case CMD_1:
execl_status = execl("./cmd1","cmd1",NULL);
break;
case CMD_2:
execl_status = execl("./cmd2","cmd2",NULL);
break;
case CMD_3:
execl_status = execl("./cmd3","cmd3",NULL);
break;
default:
printf("无此命令!!!\n");
break;
}
if(execl_status<0)
{
printf("创建错误\n");
exit(0);
}
printf("运行完毕!\n");
exit(0);
}
else{
return;
}
}
//运行cmd
void runCMD(int cmdIndex)
{
switch(cmdIndex)
{
case INVALID_COMMAND:
printf("Command Not Found \n"); //没有找到该命令
break;
case EXIT: //exit命令返回0
exit(0);
break;
default:
myFork(cmdIndex); //创建子进程运行
break;
}
}
int main()
{
pid_t pid;
char cmdStr[30]; //命令数组(最长30)
int cmdIndex; //用于显示运行哪个数据
while(TRUE)
{
printf("\n输入命令\n>>:");
scanf("%s",cmdStr);
cmdIndex = getCmdIndex(cmdStr);
runCMD(cmdIndex); //根据数字运行不同的cmd
wait(0);
}
}
①调用Fork()函数创建子进程(当前进程的副本)成功后会返回两次值,一次是在父进程中返回子进程的pid,另一次是在子进程中返回0;若创建不成功,则返回-1。
②调用exec()函数读取指定可执行文件并载入该子进程的地址空间运行,即把当前子进程替换成新的程序(cmd),此时进程的pid不变仍为fork()创建的子进程pid。