minishell的实现

minishell的实现步骤:

               1、获取标准输入,解析字符串得到命令+运行参数
               2、判断命令是否内建
               3、创建子进程,让子进程“背锅”(进行程序替换)
               4、父进程,进行进程等待

 

    重定向:改变文件描述符所对应的描述信息(改变了数据流行,数据从原本要写入的文件流向了新的文件)。
    重定向不能在父进程中完成的,父进程是需要打印数据的。
    
    minishell中重定向的实现:
    在原有字符串解析完毕的情况下,通过[ls-l >a.txt]解析之后获取得到
    argv[]={"ls","-l",">","a.txt",NULL}  
    在子进程中判断argv中是否包含>或>>来决定是否需要重定向,
    以及重定向方式(> 清空,>>追加);
    fd=open(O_TRUNC/O_APPEND);   
    dup2(fd,1)将标准输出冲顶下到指定文件中
    
    
    \n刷新缓冲区仅仅针对的标准输出文件,对其他磁盘文件并不具备刷新缓冲区效果
    系统调用因为没有缓冲区,所以不会执行刷新缓冲区
    
    程序运行从用户态切换到内核态运行(切换方法:发起系统调用/程序异常/程序中断)
    区别:完成的功能是由用户自实现接口还是系统调用接口(当前功能自实现还是系统实现)

实现代码:

/* minishell 的实现
 *  1、获取标准输入,解析字符串得到命令
 *  2、判断命令是否重建
 *  3、创建子进程,让子进程“背锅”
 *  4、父进程进行进程等待
 * */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>

char buf[1024] = { 0 };

int do_face()
{
    memset(buf,0,1024); // 将buf中的1024个字节初始化为0x00
    printf("[user@localhost]$");
    fflush(stdout);    // 刷新标准输出的缓冲区
    
    if(scanf("%[^\n]%c", buf) !=1)
    {
        getchar();
        return -1;
    }
    return 0;
}

int argc=0;
char* argv[64];

int do_prase()
{
    argc = 0;
    char* ptr=buf;
    while(ptr !='\0')
    {
        if(!isspace(*ptr))
        {
            argv[argc]=ptr;
            argc++;
            while(!isspace(*ptr) && *ptr!='\0')
            {
                ptr++;
            }
            *ptr='\0';
        }
        ptr++;
    }
    argv[argc]=NULL;
    return 0;

}


int main()
{

    while(1)
    {
        if(do_face() < 0)
        {
            continue;
        }

        if(do_prase()<0)
        {
            continue;

        }

        // 实现shell,功能
        
        if(strcmp(argv[0],"cd")==0)
        {
            // 改变工作路径
            chdir(argv[1]);
            continue;
            
        }

        // 创建子进程
        int pid =fork();
        if(pid <0)    // 创建失败
        {
            perror("fork error");
            return -1;

        }
        else if(pid ==0)   // 创建成功
        {
            // 在子进程中重定向
            int i=0;
            for(i =0 ;i < argc ;i++)
            {
                if(strcmp(argv[i], ">") == 0)
                {
                    int fd = open(argv[i+1], O_WRONLY | O_CREAT | O_TRUNC );
                    dup2(fd ,1);
                    argv[i] = NULL;

                }
                else if(strcmp(argv[i] , ">>") == 0)
                {
                    int fd = open(argv[i+1], O_WRONLY | O_CREAT | O_TRUNC );
                    dup2(fd ,1);
                    argv[i] = NULL;
                    
                }

            }
            execvp(argv[0] , argv);
            exit(-1);

        }
        wait( NULL );


    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值