Shell lab CSAPP(深入理解计算机系统)

本文详细介绍了实现一个简单的Unix Shell程序的过程,包括eval、builtin_cmd、do_bgfg、waitfg等核心功能。通过阅读PDF文档、理解作业要求并参考例子进行实践,可以实现命令解析、内置命令执行、作业控制等功能。Shell不仅是一个命令行解释器,还支持作业控制,如jobs、bg、fg等操作。
摘要由CSDN通过智能技术生成

系列文章目录


前言

这个lab可以说是我投入最认真的的一个。
前提是要把pdf所有的内容都熟读标注,把书上相应内容反复看几遍。按照书上的例子敲进去,在参照其他博客改改,就能基本满足lab的要求。

lab原始代码链接:
http://csapp.cs.cmu.edu/3e/shlab-handout.tar
lab的pdf链接:
http://csapp.cs.cmu.edu/3e/shlab.pdf

一、作业解释和要求

这个Lab主要要求实现一个最简单的Unix shell程序(貌似是tinyshell)
需要在原有框架下实现:

  • eval:主程序,用于分析、解释命令行
  • builtin_cmd:识别、解释 bulit-in 命令:如quit,fg,bg 和jobs
  • do_bgfg:执行 bg 和 fg 这些bulit-in命令
  • waitfg:等待前台程序(foreground job)完成
  • sigchld_handler:获取 SIGCHILD 信号
  • sigint_handler:获取 SIGINT(ctrl-c)信号
  • sigtstp_handler:获取SIGTSTP(ctrl-z) 信号

Unix Shells的大致介绍

Shell是一个交互的命令行解释器,并且其在用户面前运行程序。一个shell反复地打印提示,等待stdin的命令行(command line),随后按照命令行执行相应的操作。
命令行是一个以空格分隔的ASCII文本单词序列。命令行中的第一个单词是内置命令的名称或可执行文件的路径名。剩下的单词是命令行参数。如果第一个单词是内置命令,shell会立即在当前进程中执行该命令。否则,该字被假定为可执行程序的路径名。在这种情况下,shell会fork一个子进程,然后在该子进程的上下文中加载并运行该程序。由于解释单个命令行而创建的子进程统称为作业。通常,一个作业可以由多个通过Unix管道连接的子进程组成。

例如输入命令行:

tsh> jobs

这使得 shell 执行 built-in 中的 jobs 指令。
输入命令行:

tsh> /bin/ls -l -d

使得在前台运行ls程序。按照约定,shell确保当程序开始执行它的主例程时

int main(int argc, char *argv[])

其中 args 和 argv 参数有如下的值:

argc == 3
argv[0] == ‘‘/bin/ls’’
argv[1]== ‘‘-l’’
argv[2]== ‘‘-d’’

或者,键入命令行:

tsh> /bin/ls -l -d 

使得ls程序运行在后台。

Shell支持作业控制(jobs contorl)的概念,它允许用户在后台和前台之间来回移动作业,并更改作业中进程的状态(运行、停止或终止)。键入 ctrl-c 将导致一个 SIGINT 信号传递给前台作业中的每个进程。SIGINT 的默认操作是终止进程。类似地,键入 ctrl-z 将导致向前台作业中的每个进程发送 SIGTSTP 信号。SIGTSTP的默认操作是将进程置于停止状态,直到被接收方唤醒为止。比如:

  • jobs:列出正在运行和已停止的后台任务
  • bg:将已停止的后台作业更改为正在运行的后台作业。
  • fg:将已停止或正在运行的后台作业更改为正在前台运行的作业。
  • kill:杀死一个作业(进程)

二、代码

0. main主程序


/*
 * main - The shell's main routine 
 */
int main(int argc, char **argv) 
{
   
    char c;
    char cmdline[MAXLINE];
    int emit_prompt = 1; /* emit prompt (default) */

    /* Redirect stderr to stdout (so that driver will get all output
     * on the pipe connected to stdout) */
    dup2(1, 2);

    /* Parse the command line */
    while ((c = getopt(argc, argv, "hvp")) != EOF) {
   
        switch (c) {
   
        case 'h':             /* print help message */
            usage();
	    break;
        case 'v':             /* emit additional diagnostic info */
            verbose = 1;
	    break;
        case 'p':             /* don't print a prompt */
            emit_prompt = 0;  /* handy for automatic testing */
	    break;
	default:
            usage();
	}
    }

    /* Install the signal handlers */

    /* These are the ones you will need to implement */
    Signal(SIGINT,  sigint_handler);   /* ctrl-c */
    Signal(SIGTSTP, sigtstp_handler);  /* ctrl-z */
    Signal(SIGCHLD, sigchld_handler);  /* Terminated or stopped child */

    /* This one provides a clean way to kill the shell */
    Signal(SIGQUIT, sigquit_handler); 

    /* Initialize the job list */
    initjobs(jobs);

    /* Execute the shell's read/eval loop */
    while (1) {
   

	/* Read command line */
	if (emit_prompt) {
   
	    printf("%s", prompt);
	    fflush(stdout);
	}
	if ((fgets(cmdline, MAXLINE, stdin) == NULL) && ferror(stdin))
	    app_error("fgets error");
	if (feof(stdin)) {
    /* End of file (ctrl-d) */
	    fflush(stdout);
	    
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值