操作系统实验三-(1)

操作系统课程设计(三)

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。
在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值