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
,将两者内容进行对比,则可知是否正确 举例如下