zoukankan      html  css  js  c++  java
  • 实现mybash

    任务内容

    1.使用fork,exec,wait实现mybash

    查找资料:
    fork函数
    通过fork()系统调用我们可以创建一个和当前进程印象一样的新进程.我们通常将新进程称为子进程,而当前进程称为父进程.而子进程继承了父进程的整个地址空间,其中包括了进程上下文,堆栈地址,内存信息进程控制块(PCB)等.通过man手册我们可以轻松知道fork()包含的头文件<sys/types.h>和<unistd.h>,功能就是创建一个子进程.函数原型:pid_t fork(void),pid_t是带一个代表经常号pid的数据结构.如果创建成功一个子进程,对于父进程来说是返回子进程的ID.而对于子进程来说就是返回0.而返回-1代表创建子进程失败.

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

    wait函数
    int wait(int* statloc);
    int waitpid(pid_t pid, int* statloc, int options);
    这两个函数的区别如下:1. 在一个子进程终止前,wait使其调用者阻塞,而waitpid有一个选项,可使调用者不阻塞;2. waitpid()并不等待在其调用之后的第一个终止的子进程,它有若干个选项,可以控制它所等待的进程;

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

    伪代码

    #include<stdio.h>
    int main(){
    读取命令行输入内容;
    判断是否为bash中的命令;
    判断是否新建子进程并执行;
    执行命令结束;
    }
    

    mybash.c

    #include<stdio.h>
    #include<unistd.h>
    #include<stdlib.h>
    #include<sys/types.h>
    #include<sys/stat.h>
    #include<sys/wait.h>
    #include<string.h>
    int main()
    {
    while(1)
    {
    printf("20165336mybash:");
    fflush(stdout);
        char buffer[1024];
        int read_size = read(1, buffer, sizeof(buffer));
        if (read_size > 0)
        {
            buffer[read_size - 1] = 0;
        }
    
        char* bash_argv[32] = {NULL};
        int bash_index = 0;
        char* start = buffer;
        while (*start != '')
        {
            while (*start != '' && isspace(*start))
            {
                *start = '';
                start++;
            }
            bash_argv[bash_index++] = start;
            while (*start != '' && !isspace(*start))
            {
                start++;
            }
        }
        pid_t pid = vfork();
    
        if (pid < 0)
        {
            printf("vfork failure
    ");
            exit(1);
        }
        else if (pid == 0)
        {
            int i = 0;
            int flag = 0;
    
            for (; bash_argv[i] != NULL; ++i )
            {
                if (strcmp(">", bash_argv[i]) == 0)
                {
                    flag = 1;
                    break;
                }
            }
    
            int copyFd;
    
            bash_argv[i] = NULL;
    
    
            if (flag)
            {
                if (bash_argv[i+1] == NULL)
                {
                    printf("command error
    ");
                    exit(1);
                }
    
                close(1);
    
                int fd = open(bash_argv[i+1], O_WRONLY | O_CREAT, 0777);
    
                copyFd = dup2(1, fd);
            }
    
            execvp(bash_argv[0], bash_argv);
    
            if (flag)
            {
                close(1);
                dup2(copyFd, 1);
    
            }
    
            exit(1);
        }
        else 
        {
            int status = 0;
            int ret = waitpid(pid, &status, 0);
            if (ret == pid)
            {
                if (WIFEXITED(status))
                {
                    printf("exitCode is %d
    ", WEXITSTATUS(status));
                }
                else if (WIFSIGNALED(status))
                {
                    printf("signal is %d
    ", WTERMSIG(status));
                }
            }
        }
    
    }
    return 0;
    }
    

    (包含代码托管链接)

    代码链接

    3.发表知识理解,实现过程和问题解决的博客### 遇到的问题在实现bash后输入命令ls 出现问题当加入/bin/ls后方能显示当前文件夹下的内容查找资料有的说是环境变量的设置问题,未能找到很好的答案,继续探索中。

  • 相关阅读:
    P1219 [USACO1.5]八皇后 Checker Challenge 深度搜索 标记 回溯
    P2036 [COCI2008-2009#2] PERKET 深度搜索 暴力
    20201122 赛事纪录
    P4447 [AHOI2018初中组]分组 贪心
    P4995 跳跳! 贪心
    P1434 [SHOI2002]滑雪 记忆化搜索,深度搜索,动态规划
    leetcode(42)接雨水
    数据结构与算法的总纲
    leetcode(84)柱状图中最大的矩形
    leetcode(45)跳跃游戏
  • 原文地址:https://www.cnblogs.com/20165336kzq/p/10016916.html
Copyright © 2011-2022 走看看