2017-2018-1 20155320 第五周 加分题-mybash的实现

2017-2018-1 20155320 第五周 加分题-mybash的实现

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

学习函数的使用

使用man命令来查找函数的使用

  • fork函数

fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。一个进程调用fork()函数后,系统先给新的进程分配资源.

父进程从fork返回处继续执行,在父进程中,fork返回子进程PID
子进程从fork返回处开始执行,在子进程中,fork返回0

  • 其实对fork函数中子进程与父进程的调用感觉有点绕,然后又学习了一下娄老师提供的几个demo代码,运行结果如下:

    n个fork,2^n个after

    fork()返回中1代表父进程,0代表子进程

  • exec函数

fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中启动另一个程序执行的方法

  • wait函数

常用来阻塞进程,当父进程的所有子进程都还在运行,调用wait将使父进程阻塞。

mybash的实现

  • 根据娄老师上课所讲的思路,就是在父进程中用while循环来根据命令调用命令的实现1.命令以字符串的形式输入 2. pid用来区分进程

伪代码

while(1){
    输入命令
    创建子进程
    执行命令
    等待命令执行结束
}

产品代码

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#define len 100
#define MAX 100
typedef int pid_t;

char* make(char *buf)//将字符串传入参数表内
{
    char *cp;
    cp=malloc(strlen(buf)+1);
    if (cp==NULL)
    {
        fprintf(stderr,"no memory
");
        exit(1);
    }
    strcpy(cp,buf);
    return cp;
}

int change(char *buf,char *arglist[])//对于字符串进行分割
{
   int num,j,i,last;
    char buffer[len];
    num=0;
    i=0;
    while (num<MAX)
    {
        if (buf[i]=='
')
        {
            arglist[num]=NULL;
              return num;
           
        }
        if (buf[i]==' ') i++;
        last=i;
        while (buf[i]!=' ' && buf[i]!='
') i++;
        for (j=last;j<i;j++) buffer[j-last]=buf[j];
        buffer[j-last]='';
        arglist[num++]=make(buffer);
    }
    
}

int main(){
 pid_t pid;
 char *arglist[MAX];//shell指令参数表
 char buf[len];
 int x;
 while(1){
 printf("mybash~:");
  fflush(stdout);
 fgets(buf,len,stdin);//读入单行指令
x=change(buf,arglist);
/*for(x=0;x<strlen(buf)-1;x++){
  *arglist[x]=buf[0];
}*/
 pid=fork();//创建一个子进程
 if(pid<0) /* 如果出错 */
               printf("error ocurred!/n");
 if(pid==0){
   execvp(arglist[0],arglist);//执行命令
   }
  waitpid(pid,NULL,0);//等待子进程结束
 }
 return 0;
}


  • 实现结果

实现中出现的问题

  • 问题1:第一次运行时,不知道为啥命令运行不了

  • 解决1:看了几个同学的博客,说加一个/bin,但我尝试了一下仍然无法运行。出现了如下图所示情况

  • 解决2:通过仔细查看之前出现的警告,我发现我犯了个愚蠢的错误,execvp函数中需要指针传参。

  • 解决3:我尝试将buf的值赋给指针数组arglist,结果出现段错误

  • 解决4:通过网上查询,在linux下shell的简单实现,研究了一下别人的代码,给我一些启发,发现重新修改了一下buf和arglist的转换,终于正确了

原文地址:https://www.cnblogs.com/ljq1997/p/8010947.html