2017-2018-1 20155215 第五周 mybash的实现

题目要求

  • 使用fork,exec,wait实现mybash
  • 写出伪代码,产品代码和测试代码
  • 发表知识理解,实现过程和问题解决的博客(包含代码托管链接)

学习fork,exec,wait

fork

  • man fork

fork 这个英文单词在英文里是"分叉"意思, fork() 这个函数作用也很符合这个意思. 它的作用是复制当前进程(包括进程在内存里的堆栈数据)为1个新的镜像. 然后这个新的镜像和旧的进程同时执行下去. 相当于本来1个进程, 遇到fork() 函数后就分叉成两个进程同时执行了. 而且这两个进程是互不影响

exec

  • man exec

虽然使用if 对 fork() 的返回值进行判断, 实现了子进程和 主进程在if判断的范围内执行了不同的代码, 但是一旦if执行完成, 他们还是会各自执行后面的代码.
通常这不是我们期望的, 我们更多时会希望子进程执行一段特别的代码后就让他结束, 后面的代码让主程序执行就行了.
这个实现起来很简单, 在子程序的if 条件内最后加上exit() 函数就ok了.

wait

  • man wait

主程序和子程序的执行次序是随机的, 但是实际情况下, 通常我们希望子进程执行后, 才继续执行主进程.
例如对于上面的fork_1()函数, 我想先输出子进程的8个 "This is child process" 然后再输出 8个 主进程"This is parent process", 改如何做?
wait()函数就提供了这个功能, 在if 条件内的 主进程呢部分内 加上wait() 函数, 就可以让主进程执行fork()函数时先hold 住, 等子进程退出后再执行, 通常会配合子进程的exit()函数一同使用.

写出伪代码,产品代码和测试代码

  • 产品代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

#define	MAX 10	
#define	EXIT_FLAG "quit"
#define	CMD_BUFFER_SIZE	256	//命令缓冲区大小

int main(void)
{
     char * argv[MAX];
     char cmdBuffer[CMD_BUFFER_SIZE];
     int pid;
     int status;
     int paraNum;	//参数个数

     while(1)	
     {
          printf("mybash >");
          fflush(stdout);	//及时输出命令提示符
          fgets(cmdBuffer, CMD_BUFFER_SIZE, stdin);
          if(cmdBuffer[0] == '\n')
          {
               continue;
          }
          if(cmdBuffer[strlen(cmdBuffer)-1] == '\n')
               {//去掉末尾回车符
                      cmdBuffer[strlen(cmdBuffer)-1] = 0;
                }
          if(!strcmp(cmdBuffer, EXIT_FLAG))
          {
                    break;
          }

          //分割参数
          paraNum = 1;
          argv[0] = strtok(cmdBuffer, " ");	//空格进行分割
          while( (paraNum < MAX) &&(argv[paraNum] = strtok(NULL, " ")) )
               {
                    paraNum++;
               }
         //创建子进程以执行命令
          pid = vfork();
          if( pid == 0 )
          {//子进程执行命令
                execvp(argv[0], argv);
                perror("execvp");
                exit(EXIT_FAILURE);
          }else if( pid < 0 )
               {//错误
                    perror("vfork");
                    exit(EXIT_FAILURE);
                    }else
                       {
                              waitpid(pid, &status, 0);	//等待子进程结束
                              }
                    }
          return 0;
}
posted @ 2017-12-08 11:57  xuanyan  阅读(129)  评论(0编辑  收藏  举报