mybash的实现

Posted musea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybash的实现相关的知识,希望对你有一定的参考价值。

2018-2019-1 20165226《信息安全系统设计基础》 bash的实现

目录


一、学习fork,exec,wait
二、实现bash

一、学习fork,exec,wait


1、fork

  • 格式
//头文件
#include <unistd.h>
//函数定义
pid_t fork( void );

技术分享图片

返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1函数说明:一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。

  • 举例
#include <stdio.h>
#include <unistd.h>
void main()
{
    int i;
    printf("hello, %d
",getpid());
    i=2;
    fork();
    printf("var %d in %d
", i, getpid());
}

结果:
技术分享图片

2、exec

  • exec家族

    只有)int execve(const char *path, char *const argv[], char *const envp[]);是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。

  • 书写格式:

    先定义一个指针数组:char *argv[]={“ls”,”-l”,(char *)0}
    用execv调用ls:execv(“/bin/ls”,argv)
    如果用execvp
    execvp(“ls”,argv) //直接写ls就可以了

    技术分享图片

3、wait

  • 函数原型
#include<sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status) 

参数status用来保存被收集进程退出时的一些状态,它是一个指向int类型的指针。进程一旦调用了wait,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果让它找到了这样一个已经变成僵尸的子进程, wait就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找到这样一个子进程,wait就会一直阻塞在这里,直到有一个出现为止。
技术分享图片

返回目录

二、实现bash


  • 伪代码
while(1)
{
    fgets(命令行输入);
    if(内置的shell命令)
    {
        解释命令;
    }
    else if(可执行文件)
    {
        新的子进程加载并运行文件;
    }
}
  • 代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
#define MAX 128

void eval(char *cmdline);
int parseline(char *buf, char **argv);
int builtin_command(char **argv);

int main()
{
    char cmdline[MAX];

    printf("This is 20165226's bash!
");
    while(1)
    {
        printf("> ");
        fgets(cmdline, MAX, stdin);
        if(feof(stdin))
            exit(0);
        eval(cmdline);
    }
}

void eval(char *cmdline)
{
    char *argv[MAX];
    char buf[MAX];
    int bg;
    pid_t pid;
    strcpy(buf,cmdline);
    bg = parseline(buf,argv);
    if(argv[0]==NULL)
        return;
    if(!builtin_command(argv))
    {
        if((pid=fork()) == 0)
        {
            if(execvp(argv[0],argv) < 0)
            {
                printf("%s : Command not found.
",argv[0]);
                exit(0);
            }
        }
    }
    if(!bg)
    {
        int status;
        if(waitpid(-1,&status,0) < 0)
        printf("waitfg: waitpid error!");
    }
    else
    {
        printf("%d %s",pid, cmdline);
        return;
    }
}

int builtin_command(char  **argv)
{
    if(!strcmp(argv[0], "quit"))
        exit(0);
    if(!strcmp(argv[0],"&"))
        return 1;
    return 0;
}

int parseline(char *buf,char **argv)
{
    char *delim;
    int argc;
    int bg;

    buf[strlen(buf)-1]=' ';
    while(*buf && (*buf == ' '))
        buf++;

    argc=0;
    while( (delim = strchr(buf,' ')))
    {
        argv[argc++] = buf;
        *delim= '';
        buf = delim + 1;
        while(*buf && (*buf == ' '))
            buf++;
    }
    argv[argc] = NULL;
    if(argc == 0)
        return 1;
    if((bg=(*argv[argc-1] == '&')) != 0)
        argv[--argc] = NULL;

    return bg;
}
  • 测试代码
ls
ls -a
git --version
  • 结果
    技术分享图片

返回目录[]

以上是关于mybash的实现的主要内容,如果未能解决你的问题,请参考以下文章

mybash的实现

20165324_mybash的实现

20165322 第七周 mybash 的实现

20165223 《信息安全系统设计基础》 实现mybash

mybash的实现

20165220 mybash