csapp实验4:shell lab

前言

我之前不是做不下去吗,关于这个shell lab,这次再尝试后发现也没这么没头绪了,虽然不是自己独立做出来的,但是确实真正看懂了,所以千万不要急躁,不要焦虑啊,认认真真去搞就够了,之后我再做一个malloc lab以及补上实验3的lab就不做了,主要是自己也对cache lab以及buffer lab不太感兴趣。至于proxy lab是与网络编程相关的,就不做了。

实验

该实验就是写几个函数,补上一个简单的shell
可通过make rtestxx来知道正确答案,通过make testxx来测试自己,一共有16个测试样例

eval

void eval(char *cmdline) 
{
    char *argv[MAXARGS];
    char buf[MAXLINE];
    int bg; 
    pid_t pid;

    sigset_t mask_all,mask_one,mask_pre;
    sigemptyset(&mask_one);
    sigfillset(&mask_all);
    sigaddset(&mask_one,SIGCHLD);
    strcpy(buf,cmdline);
    bg=parseline(buf,argv);
    if(argv[0]==NULL)
        return;
    
    if(!builtin_cmd(argv)){
        sigprocmask(SIG_BLOCK,&mask_one,&mask_pre);//防止竞争条件,需要阻塞信号
        if((pid=fork())==0){
            if(setpgid(0,0)<0){ //设置进程组,其id为该进程的pid
                perror("pgid error");
                exit(0);
            }
            sigprocmask(SIG_SETMASK,&mask_pre,NULL);
           
            if(execve(argv[0],argv,environ)<0){
                printf("%s:Command not found\n",argv[0]);
                exit(0);
            }
        }
        int i;
        if(!bg){//如果是前台进程,肯定要阻塞
            sigprocmask(SIG_BLOCK,&mask_all,&mask_pre);//阻塞全部信号,防止中断
            for(i=0;i<MAXJOBS;i++){
                if(jobs[i].state==UNDEF){
                    addjob(&jobs[i],pid,FG,cmdline);
                    break;
                }
            }
            sigprocmask(SIG_SETMASK,&mask_pre,NULL);
            waitfg(pid);
        }else{//后台进程
            sigprocmask(SIG_BLOCK,&mask_all,&mask_pre);
           // addjob(&jobs[maxjid(jobs)+1],pid,BG,cmdline);
            for(i=0;i<MAXJOBS;i++){
                if(jobs[i].state==UNDEF){
                    addjob(&jobs[i],pid,BG,cmdline);
                    break;
                }
            }
            printf("[%d] (%d) %s",pid2jid(pid),pid,cmdline);
            sigprocmask(SIG_SETMASK,&mask_pre,NULL);
        }
    }
    return;
}

builtin_cmd

int builtin_cmd(char **argv) //主要是判断是不是内置命令
{
    if(!strcmp(argv[0],"quit"))
        exit(0);
    if(!strcmp(argv[0],"&"))
        return 1;
    if(!strcmp(argv[0],"jobs")){
        listjobs(jobs);
        return 1;
    }
    if(!strcmp(argv[0],"bg")){//唤醒停止的后台作业
        do_bgfg(argv);
        return 1;
    }
    if(!strcmp(argv[0],"fg")){//将后台作业改为前台
        do_bgfg(argv);
        return 1;
    }   
    return 0;
}

db_bgfg

void do_bgfg(char **argv) 
{   
    if(argv[1]==NULL){
        app_error("error");
        return;
    } 
    struct job_t *job_ptr=NULL;
    if(argv[1][0]=='%'){ //这代表是输入的是作业
       if(argv[1][1]>='0'&&argv[1][1]<='9'){
           int jid=atoi(argv[1]+1);
           job_ptr=getjobjid(jobs,jid);
           if(job_ptr==NULL){
               printf("%s:no such job\n",argv[1]+1);
               return;
           }
       }
    }else if(argv[1][0]>='0'&&argv[1][0]<='9'){ //这是输入进程
          pid_t pid=atoi(argv[1]);
          job_ptr=getjobpid(jobs,pid);
          if(job_ptr==NULL){
              printf("%s:no such process\n",argv[1]);
              return;
          }
    }
    kill(-job_ptr->pid,SIGCONT);//继续运行
    if(!strcmp(argv[0],"bg")){ //后台进程,继续运行
        job_ptr->state=BG;
        printf("[%d] (%d) %s",job_ptr->jid,job_ptr->pid,job_ptr->cmdline);
    }else{ //前台进程,需要等待
        job_ptr->state=FG;
        waitfg(job_ptr->pid);
    }
    return;
}

waitfg

void waitfg(pid_t pid)
{
    sigset_t mask;  
    sigemptyset(&mask); 
    while(pid==fgpid(jobs))
        sigsuspend(&mask);//第一时间会挂起,这样就不会耗费那么多cpu资源,直到
        //有信号传递过来,即是终止还是执行信号处理函数
    return;
}

sigchld_handler

void sigchld_handler(int sig) //信号SIGCHLD的信号处理函数
{
    sigset_t mask_all,mask_pre;
    pid_t pid;
    sigfillset(&mask_all);
    int status;
    while((pid=waitpid(-1,&status,WNOHANG|WUNTRACED))>0){
        sigprocmask(SIG_BLOCK,&mask_all,&mask_pre); //阻塞
          if(WIFEXITED(status)){//正常终止
             deletejob(jobs,pid);
          }else if(WIFSIGNALED(status)){//非正常终止
             int jid=pid2jid(pid);
             printf("Job [%d](%d) terminated by signal %d\n ",jid,pid,WTERMSIG(status));
             deletejob(jobs,pid);
          }else if(WIFSTOPPED(status)){//挂起,停止了
              struct job_t *job_ptr=getjobpid(jobs,pid);
              int jid=pid2jid(pid);
              printf("Job [%d] (%d) stopped by signal %d\n",jid,pid,WSTOPSIG(status));
              job_ptr->state=ST;
          }
          sigprocmask(SIG_SETMASK,&mask_pre,NULL);
    }
    return;
}

sigint_handler

void sigint_handler(int sig) //ctrl-c的信号处理函数
{
    pid_t pid=fgpid(jobs);
    kill(-pid,sig);//发送信号给其进程组
    return;
}

sigstp_handler

void sigtstp_handler(int sig) //ctrl-z的信号处理函数
{
    pid_t pid=fgpid(jobs);
    kill(-pid,sig);
    return;
}

结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值