mybash的实现

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

目录


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

一、学习fork,exec,wait

**** ## 1、fork - 格式 ``` //头文件 #include //函数定义 pid_t fork( void ); ``` ![](https://img2018.cnblogs.com/blog/1047870/201811/1047870-20181125180650571-33288388.png)

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

  • 举例
#include <stdio.h>
#include <unistd.h>
void main()
{
    int i;
    printf("hello, %d\n",getpid());
    i=2;
    fork();
    printf("var %d in %d\n", 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!\n");
    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.\n",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= '\0';
        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
  • 结果

返回目录![]

posted on 2018-11-25 18:09  musea  阅读(203)  评论(0编辑  收藏  举报