CSAPP - 一个简单的Shell

Posted sesiria

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSAPP - 一个简单的Shell相关的知识,希望对你有一定的参考价值。

Shell命令在是最常用的一个和操作系统交互的工具。

shell命令的基本执行过程是:

1)从stdin来读取用户的command。

2)对command进行解析,并判断是否为buildin command

3)如果是buildin command则执行buildin command

4)如果非buildin command,则执行fork命令,然后在fork的子进程中执行execve创建新的program。

其中还涉及到对输入command进行parse的简单过程。

5)如果要对进程的切换fg, bg等。需要涉及到signal切换等。(暂时不支持)

一下是一个最简单的shell, 依赖书籍csapp.c 以及 csapp.h

/* Simple Shell command 
* linux>gcc -o shellex shellex.c csapp.c -lpthread
*/

#include "csapp.h"
#define MAXARGS     128

/*Function prototypes */
void eval(char *cmdline);
int parseline(char * buf, char **argv);
int builtin_command(char **argv);

int main()
{
    char cmdline[MAXLINE];      /* Command line */

    while(1) {
        /* Read */
        printf("> ");
        Fgets(cmdline, MAXLINE, stdin);
        if(feof(stdin))
            exit(0);
        
        /* Evaluate */
        eval(cmdline);
    }
}

/* eval - Evaluate a command line */
void eval(char *cmdline)
{
    char *argv[MAXARGS];        /* Argument list execve() */
    char buf[MAXLINE];          /* Holds modified command line */
    int bg;                     /* Should the job run in bg or fg? */
    pid_t pid;                  /* Process id */

    strcpy(buf, cmdline);
    bg = parseline(buf, argv);
    if(argv[0] == NULL)
        return;                 /* Ignore empty lines */
    
    if(!builtin_command(argv)) {
        if((pid = Fork()) == 0) {       /* Child runs user job */
            if(execve(argv[0], argv, environ) < 0)  {
                printf("%s: Command not found.\\n", argv[0]);
                exit(EXIT_SUCCESS);
            }
        }

        /* Parent waits for foreground job to terminate */
        if(!bg) {
            int status;
            if(waitpid(pid, &status, 0) < 0)
                unix_error("waitfg: waitpid error");
        }
        else {
            printf("%d %s", pid, cmdline);
        }
    }
    return;
}

/* If first arg is a builtin command, run it and return true */
int builtin_command(char **argv)
{
    if(!strcmp(argv[0], "quit"))    /* quit command */
        exit(EXIT_SUCCESS);
    if(!strcmp(argv[0], "&"))       /* Ignore singleton & */
        return 1;
    return 0;                       /* Not a builtin command */
}

/* parseline - Parse the command line and build the argv array */
int parseline(char *buf, char ** argv)
{
    char * delim;                   /* Points to first space delimiter */
    int argc;                       /* Number of args */
    int bg;                         /* Background job? */

    buf[strlen(buf) - 1] = ' ';     /* Replace trailing '\\n' with space */
    while(*buf && (*buf == ' '))    /* Ignore leading spaces */
        buf++;
    
    /* Build the argv list */
    argc = 0;
    while((delim = strchr(buf, ' '))) {
        argv[argc++] = buf;
        *delim = '\\0';
        buf = delim + 1;
        while(*buf && (*buf == ' '))    /* Ignore spaces */
            buf++;
    }
    argv[argc] = NULL;

    if(argc == 0)                   /* Ignore blank line */
        return 1;
    
    /* Should the job run in the background? */
    if((bg = (*argv[argc - 1] == '&')) != 0)
        argv[--argc] = NULL;
    
    return bg;
}

执行最简单的命令:

以上是关于CSAPP - 一个简单的Shell的主要内容,如果未能解决你的问题,请参考以下文章

CSAPP - 一个简单的Shell

CSAPP Lab:Shell Lab——理解进程控制的秘密

CSAPP Shell Lab

CSAPP Shell Lab

CSAPP随笔:hello world到底是怎么运行的?

csappshlab实验分享