CS:APP Shell Lab解决办法

Shell代码

1.eval

void eval(char *cmdline) 
{
    
    
    //第一步,初始化各变量和信号阻塞全集
    char *argv[MAXLINE];
    char buf[MAXLINE];
    int bg;
    pid_t pid;//储存当前前台pid
    sigset_t mask;

    stpcpy(buf,cmdline);
    bg = parseline(buf,argv);

    if (argv[0] == NULL)
    {
    
    
        return;                 /*ignore empty line*/
    }

    if (!builtin_cmd(argv))     /*if not a build in cmd*/
    {
    
    
        sigemptyset(&mask);
        sigaddset(&mask,SIGCHLD);
        sigprocmask(SIG_BLOCK,&mask,NULL);   /*block the SIGCHLD signal*/


        if ((pid = fork()) == 0)
        {
    
    
            sigprocmask(SIG_UNBLOCK,&mask,NULL);   /*unblock the SIGCHLD signal in child*/
            setpgid(0,0);  /*puts the child in a new process group*/

            if (execve(argv[0],argv,environ) < 0)
            {
    
    
                printf("%s: Command not found\n",argv[0]);
                exit(0);
            }
        }

        addjob(jobs,pid,bg?BG:FG,cmdline);    /*add job into jobs*/
        sigprocmask(SIG_UNBLOCK,&mask,NULL);   /*unblock the SIGCHLD signal in parent*/

        bg ? printf("[%d] (%d) %s",pid2jid(pid),pid,cmdline):waitfg(pid);   /*do in background or foreground*/
    }
    return;
}

2.builtin_cmd

int builtin_cmd(char **argv) 
{
    
    
    if(!strcmp(argv[0],"quit"))
        exit(0);
    if(!strcmp(argv[0],"&"))
        return 1;
    if(!strcmp(argv[0],"bg")||!strcmp(argv[0],"fg")){
    
    
        do_bgfg(argv);
        return 1;
    }
    if(!strcmp(argv[0],"jobs")){
    
    
        listjobs(jobs);
        return 1;
    }

    return 0;     /* not a builtin command */
}

3.do_bgfg

void do_bgfg(char **argv) 
{
    
    
	pid_t pid;
    struct job_t *job;
    char *id = argv[1];

    if (id == NULL)//id is null
    {
    
    
        printf("%s command requires PID or %%jobid argument\n",argv[0]);
        return;
    }

    if (id[0] == '%')//the argument is a job id
    {
    
    
        int jid = atoi(&id[1]);
        job = getjobjid(jobs,jid);
        if (job == NULL)
        {
    
    
            printf("%%%d: No such job\n",jid);
            return;
        } 
    }
    else if (isdigit(id[0]))
    {
    
    
        pid = atoi(id);
        job = getjobpid(jobs,pid);
        if (job == NULL)
        {
    
    
            printf("(%d): No such process\n",pid);
            return ;
        }
    }
    else
    {
    
    
        printf("%s: argument must be a PID or %%jobid\n", argv[0]);
        return;
    }

    kill(-(job->pid),SIGCONT);//send the SIGCONT to the pid

    if (!strcmp(argv[0],"bg"))//set job state ,do it in bg or fg
    {
    
    
        job->state = BG;
        printf("[%d] (%d) %s", job->jid, job->pid,job->cmdline);
    }
    else
    {
    
    
        job->state = FG;
        waitfg(job->pid);
    }
    return;
}

(这里的kill大写不能识别,也不知道是为啥

4.waitfg

void waitfg(pid_t pid)
{
    
    
    while (pid == fgpid(jobs))
    {
    
    
        sleep(0);
    }
    return;
}

5.sigchld_handler

void sigchld_handler(int sig)
{
    
    
    pid_t pid;
    int status;
    while((pid = waitpid(-1,&status,WNOHANG|WUNTRACED))>0){
    
    
        if(WIFEXITED(status)){
    
      //正常结束,删掉
            deletejob(jobs,pid);
        }
        if(WIFSIGNALED(status)){
    
    //僵尸进程,删掉
            printf("Job [%d] (%d) terminated by signal %d\n",pid2jid(pid),pid,WTERMSIG(status));
            deletejob(jobs,pid);
        }
        if(WIFSTOPPED(status)){
    
    //是个停止进程,不需要回收
            printf("Job [%d] (%d) stopped by signal %d\n",pid2jid(pid),pid,WSTOPSIG(status));
            struct job_t *job = getjobpid(jobs,pid);
            if(job !=NULL )job->state = ST;//设置状态为ST
        }
    }
    return;
}

6.sigint_handler

void sigint_handler(int sig) 
{
    
    
	pid_t pid = fgpid(jobs);
    if(pid != 0){
    
    
        kill(-pid,SIGINT);
        /*let the sigchld_handler to delete the job in jobs?*/
    }
    return;
}

7.sigtstp_handler

void sigtstp_handler(int sig) 
{
    
    
	pid_t pid = fgpid(jobs);

    if (pid != 0)
    {
    
    
        struct job_t *job = getjobpid(jobs,pid);
        if (job->state == ST)
        {
    
    
            return;
        }
        else
        {
    
    
            kill(-pid,SIGTSTP);
        }
    }
    return;
}

测试

每次修改过tsh.c代码后,都要在Terminal中make一下看是否有错误 如图即是通过
在这里插入图片描述
输入make test01,将得到的结果与trace01.txt中的内容进行对比,或者再次输入make rtest01,将两者内容进行对比,则可知是否正确 举例如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45784337/article/details/111559311
今日推荐