回 帖 发 新 帖 刷新版面

主题:问一道unix的编程题,谢谢帮忙。。

A1

写一个小基本的Unix shell,解析命令,并执行命令。请注意,我们将能够执行简单命令没有Shell重定向或管道。基本上您应该能够执行:cat,cp, ls和各种其他不带参数简单的命令。


你的shell应该做到以下几点: 

1 。采取的输入字符串并解析成词用白空格分开(tab,blanks等) 。它应一次读一行(换行符终止) 。你的shell在EOF时退出。


2 。执行命令使用fork, execvp ,wait,和exit。 即shell应fork一个子进程,让子进程调用exec,并等待子进程终止。小心关于分叉,即执行ps或PS -elf(或上方) ,使确认你没有大量的释放的子进程。 这可能是由于父进程与子进程仍在执行或因其他原因终止的父进程然后才可以请等待。

3. 加三个内部指令;
  3.1 
    %myshell string...
  调用system去执行string。也就是说你的shell执行的是不含有myshell的语句。  

  3.2
    %mydebug
  重新显示最后一条命令,看看它是不是一天内部指令(myshell/mydebug/chdir).

  3.3
    % chdir somedirectory
  当前工作目录是一个正在运行的进程的属性。换句话说,你需要用一个系统调用来改变shell的目录。


A2

增强A1中shell的功能。


要求:

1. 执行后台命令-如果一行的最后一个字符是“&”,就不等待。
    例如:
    myshell> ls &
   基本思想:
    读到字符&是不要调用wait或waitpid命令。如果没有读到字符&调用等待。

2.写一个小程序,你可以执行sleep和wait一个1~10秒随机时间,用它来测试下一个功能。调用mysleep这个程序。

3 。修改shell使用waitpid和SIGCHILD信号收获信号手柄的僵尸,它不能阻止(除非您需要为特定的PID ) 。 您应该能够处理案件# 1 , # 2都为
拦截和非阻塞过程。 

4 。内置的历史命令使用内存分配的链表的命令。 您应该能够执行任何命令的列表基于!<number> 。 
例如, 
( myshell ) % !5
打印第五命令(要你经过计算得出) 。您应该可以打印的历史记录列表通过内置的历史命令。您应该只保留过去10命令。 

回复列表 (共2个回复)

沙发

这道题我接下了,给我几天时间.毕竟平时还要上班.

板凳

一个中午就搞定了A1,但办公室的Windows无法通过编译,晚上回家调试,先把代码放出来:
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<string.h>
#define CMDMAXLENG 255
#define HINTSIGN "$"
#define SEPS " \t"

#define IN_CMD_2 "mydebug"
#define IN_CMD_3 "chdir"

#define ERR_FORK "fork failed\n"
#define ERR_EXEC "execvp failed\n"
#define ERR_WAIT "waitpid failed\n"
#define ERR_CHDIR "Path name is Wrong\n"

char s_shcmd[CMDMAXLENG];
char s_lastcmd[CMDMAXLENG];
char *shname;
char *cmdname;
char *cmdargv[CMDMAXLENG];

int analyse(){
    int i, sign;

    cmdname=strtok(s_shcmd,SEPS);
    if(!strcmp(cmdname,shname)){
        sign = 1;
        cmdname = strtok(NULL,SEPS);
    }
    else if(!strcmp(cmdname,IN_CMD_2))
        return 2;
    else if(!strcmp(cmdname,IN_CMD_3))
        sign = 3;
    else
        sign = 4;

    cmdargv[0]=cmdname;
    i=1;
    while(cmdargv[i++]=(char*)strtok(NULL,SEPS));
    return sign;
}

void docmd(){
    pid_t pid;

    if((pid=fork())<0){
        printf(ERR_FORK);
        return;
    }else if(pid==0)
        if(execvp(cmdname,cmdargv)<0){
            printf(ERR_EXEC);
            return;
        }
    if(waitpid(pid,NULL,0)<0){
        printf(ERR_WAIT);
        return;
    }
    return;
}

int main(int argc,char **argv){
    shname=argv[0];

    while(1){
        printf(HINTSIGN);
        if(gets(s_shcmd)==EOF) break;
        strcpy(s_lastcmd,s_shcmd);
        switch(analyse()){
        case 2:
            puts(s_lastcmd);
            break;
        case 3:
            if(!chdir(cmdargv[1])){
                printf(ERR_CHDIR);
            }
            break;
        case 1:
            if(cmdname==NULL) break;
        case 4:
            docmd();
        }
    }
    return 0;
}

我来回复

您尚未登录,请登录后再回复。点此登录或注册