• Linux minishell的简单实现


    shell:命令行解释器,捕捉用户输入,根据输入的信息运行指定的命令程序。

    利用进程终止,等待,替换既可以完成简单的minishell,我们分析一下shell的功能就是捕捉用户输入,对用户输入进行处理,进行程序替换,进程等待防止出现僵尸进程

    1. 捕捉用户输入

    捕捉输入吗scanf_s就好了呀,不行!scanf_s遇到空格就停止了,gest(char * buf);从标准输入读取一行数据" pwd ..";

    2.字符串解析

    得到命令名称和运行参数” pwd  .. “ 把他放到argv数组里面去

    3.创建子进程

    创建子进程给子进程进行程序替换,并设置运行参数 因为是bin目录下的那些程序所以选择esec函数簇里面的execvp(argv[ 0 ],argv)

    不能直接对shell进行替换,因为替换后运行完新的程序进程就退出了,如果替换了shell,shell运行完就会退出,万一要是运行的指令崩溃了shell也就崩溃了,因此要创建子进程让子进程运行指令

    我们来看看为啥替换完新的进程原先进程就退出了

    这里实现两端代码

    example:

    1. #include
    2. //程序是有运行参数和环境变量的
    3. //程序的运行参数在给予的时候是运行程序一空格间隔跟在程序之后的
    4. //程序的运行参数,就会被保存在argc这个字符数组中
    5. //程序的环境变量,就会保存在env这个字符数组中,或者有个全局变量environ
    6. int main(int argc, char *argv[], char *env[])
    7. {
    8. extern char **environ;
    9. printf("程序参数个数: %d \n",argc);
    10. printf("程序运行参数: \n");
    11. for(int i = 0;argv[i] != NULL;i++)
    12. {
    13. printf("\t %s \n",argv[i]);
    14. }
    15. printf("程序的环境变量: \n");
    16. for(int i = 0;environ[i] != NULL;i++)
    17. {
    18. printf("\t %s \n",environ[i]);
    19. }
    20. return 0;
    21. }

    和一段exec.c来验证 

    1. #include
    2. #include
    3. int main()
    4. {
    5. extern char **environ;
    6. printf("hello !\n ");
    7. char *argv [] = {"./example" ,"-a" , "-l" , "-c", NULL };
    8. execve("./example", argv, environ);//程序替换
    9. printf("can you see me ?");
    10. }

    我们能看见can you see me ? 吗

     

    是看不见的 ,所以是为啥要fork一个子进程

     

    4.进程等待

    防止子进程运行完指令退出后成为僵尸进程

    5.代码实现

    1. int main()
    2. {
    3. while(1)
    4. {
    5. //字符串捕捉
    6. printf("[username@hostname]$ ");
    7. fflush(stdout);
    8. char input[1024] = {0};
    9. fgets(input,1023,stdin);
    10. input[strlen(input) - 1] = '\0';
    11. printf("[%s]\n",input);
    12. //字符串解析(把指令能拿出来)
    13. char *ptr = input;
    14. char *argv[32] = {NULL};
    15. int argc = 0;
    16. while(*ptr != '\0')
    17. {
    18. if(*ptr == ' ')
    19. {
    20. ptr++;
    21. continue;
    22. }
    23. argv[argc] = ptr;
    24. argc++;
    25. while(*ptr != '\0' && *ptr != ' ')
    26. {
    27. ptr++;
    28. }
    29. *ptr = '\0';
    30. ptr++;
    31. }
    32. argv[argc] = NULL;
    33. for(int i = 0;argv[i] != NULL;i++)
    34. {
    35. printf("[%s]\n",argv[i]);
    36. }
    37. //子进程替换
    38. int pid = fork();
    39. if(pid == 0)
    40. {
    41. execvp(argv[0],argv);
    42. exit(-1);//替换失败就退出不要接管成第二个shell
    43. }
    44. wait(NULL);//进程等待
    45. }
    46. return 0;
    47. }

    结果展示

    应用进程控制实现简单的shell

     

  • 相关阅读:
    Nginx可以通过配置文件实现三种常见的负载均衡方式
    CMake
    Spring5完整版详解
    从小白到大咖:软件测试工作半年心得分享!总结我掉的4个坑…
    17.3.2.5 灰度(内存处理)
    勒索病毒最新变种.helper勒索病毒来袭,如何恢复受感染的数据?
    【Unity3D】灯光组件Light
    系统架构师备考倒计时16天(每日知识点)
    python 导入 包,模块,类,函数
    总结改变和获取 url 的方法 (包括 umi,react-router,原生)
  • 原文地址:https://blog.csdn.net/qq_50119037/article/details/127513987