20165322 第七周 mybash 的实现

mybash的实现

要求

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

相关函数的作用

  • fork

    • fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间、堆、栈等资源的副本。注意,子进程持有的是上述存储空间的“副本”,这意味着父子进程不共享这些存储空间。linux将复制父进程的地址空间内容给子进程,因此,子进程由了独立的地址空间。),也就是这两个进程做完全相同的事。
    • 在父进程中,fork返回新创建子进程的进程ID;
    • 在子进程中,fork返回0;
    • 如果出现错误,fork返回一个负值
  • exec

    • exec函数族可以根据指定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段。在执行完后,原调用进程的内容除了进程号外,其它全部被新程序的内容替换了。另外,这里的可执行文件既可以是二进制文件,也可以是Linux下任何可执行脚本文件。
  • wait

    • wait()会暂时停止现在进程的执行,直到有信号来到或子进程结束。假如在调用wait()时子进程已结束,则wait()会立即返回子进程结束状态值。

伪代码

while(1)
{
    输出用户信息
    读取用户输入命令存入数组和文件
    调用fork()函数,若返回值不为0,则调用wait()
    若返回值为0,调用exec()
}

产品代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <sys/wait.h>
#define N 100
#define order_length 128
#define order_num 64
#define empty 0
#define chars 1
void main()
{ 
   while(1) {
    struct passwd *my_info;
    char path[N];
    my_info = getpwuid(getuid());
    getcwd(path, sizeof(path));
    printf("[%s@%s]$ ", my_info->pw_name, path);//输出用户及路径

    char str[N];
    char a[N];
    char *argv[N]={NULL};
    char *envp[]={0,NULL};
        int i,j = 0, flag=1;
    fgets(str,N,stdin);  //读取输入的命令
    str[N - 1] = '';
    if(feof(stdin))
        {
            printf("error");
            exit(0);
        }
    for(i=0;str[i]!=''&&i<N&&j<N;i++) {
        if(str[i] == ' ' || str[i] == '
') {
          flag=1;
          str[i] = '';
      }
      else if(flag==1) {
          argv[j++] = &str[i];
          flag=0;
      }
     }
     if(fork() != 0) wait(NULL);   //调用fork()
        else {
    execvp(argv[0], argv);
    perror("execlp error");
    exit(0);
     }
 }
}

测试结果

测试了ls,ls -l``tree``clear指令,测试截图如下:

尚有一部分命令无法实现,例如“cd”等等……

原文地址:https://www.cnblogs.com/wangyaojia/p/10017369.html