前言
我之前不是做不下去吗,关于这个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;
}