zoukankan      html  css  js  c++  java
  • 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
    ",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
    
    • 结果

    返回目录![]

  • 相关阅读:
    ADO.NET
    VS调SQL中存储过程实现登陆
    摇奖
    面向对象、类、字段、属性、构造函数、析构函数
    打架
    2012/7/26Extjs笔记_Ext.grid.EditorGridPanel
    2012/7/30sql2005学习笔记
    SVN版本冲突解决办法(非加锁)
    2012/7/30sqlserver2005学习随笔
    struts环境搭建
  • 原文地址:https://www.cnblogs.com/musea/p/10016466.html
Copyright © 2011-2022 走看看