• Linux:简易Shell


    文章目录


    全文约 1516 字,预计阅读时长: 6分钟


    前言

    • C 库函数 char *fgets(char *str, int n, FILE *stream) 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。
      • 当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
      • 如果成功,该函数返回相同的 str 参数。
      • 如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针。如果发生错误,返回一个空指针。
    • C 库函数 char *strtok(char *str, const char *delim) 分解字符串 str 为一组字符串,delim 为分隔符。
      • delim – 包含分隔符的 C 字符串。
      • 该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针。
      • 会自动处理多个相同分割字符串的情况。
      /* 获取第一个子字符串 */
       token = strtok(str, s);
       
       /* 继续获取其他的子字符串 */
       while( token != NULL ) {
          printf( "%s\n", token );
        
          token = strtok(NULL, s);
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • chdir函数: int chdir(const char *path);

      • 参数:path可以是绝对目录或者相对目录
      • 功能:改变当前工作目录
      • 返回值:成功返回0,失败返回-1
    • 命令提示符那一栏可以通过相关函数获得。


    Shell

    1. 获取命令行
    2. 解析命令行
    3. 建立一个子进程(fork)
    4. 替换子进程(execvp)
    5. 父进程等待子进程退出(waitpid)
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #define NUM 128
    #define SIZE 32
    
    char command_line[NUM];
    char *command_parse[SIZE];
    
    int main()
    {
        while(1){
            memset(command_line, '\0', sizeof(command_line));
            printf("[whb@myhost 我的shell]$ ");
            fflush(stdout);
            //1. 数据读取
            if(fgets(command_line, NUM-1, stdin)){
                command_line[strlen(command_line) - 1] = '\0';
                //ls -a -l -i
                //2. 字符串(命令行数据分析)
                int index = 0;
                command_parse[index] = strtok(command_line, " ");
                while(1){
                    index++;
                    command_parse[index] = strtok(NULL, " ");
                    if(command_parse[index] == NULL){
                        break;
                    }
                }
                //3. 判断命令 //a. 内置命令 //b. 第三方命令
                if(strcmp(command_parse[0], "cd") == 0 && chdir(command_parse[1]) == 0){
                    continue;
                }
                // 执行非内置命令
                if(fork() == 0){
                    //子进程
                    execvp(command_parse[0], command_parse); // ls  ls -a -i -l
                    exit(1);
                }
                int status = 0;
                pid_t ret = waitpid(-1, &status, 0);
                if(ret > 0 && WIFEXITED(status)){
                    printf("Exit Code: %d\n", WEXITSTATUS(status));
                }
            }
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    参考

    • C教程
      - 拆开都懂,放一块儿我仿佛就是个韩寒
  • 相关阅读:
    VR酒店虚拟仿真情景实训教学演示
    唐诗的四个阶段
    LQR与LQG问题
    Leetcode160. 相交链表(双指针)
    JAVA计算机毕业设计智能化车辆管理综合信息平台Mybatis+源码+数据库+lw文档+系统+调试部署
    神经网络阈值是什么意思,神经网络的权值和阈值
    E2. Unforgivable Curse (hard version)
    MySQL——备份和还原
    STM32H7 USART 时钟初始化
    使用一个命令使您的 Python 代码更优雅、更易读或更现代
  • 原文地址:https://blog.csdn.net/WTFamer/article/details/126062807