Linux下的简易shell实现

  • Linux系统的shell作为操作系统的外壳,为用户提供使用操作系统的接口。
  • 它是命令语言、命令解释程序及程序设计语言的统称。
  • 相当于bash的一个子进程,父进程等待,子进程进行程序替换。
  • shell充当一个桥梁:将使用者的命令翻译给核心(kernel)处理;同时,将核心的处理结果翻译给使用者。
  • shell在你成功地登录进入系统后启动,并始终作为你与系统内核的交互手段直至你退出系统。
  • 你系统上的每位用户都有一个缺省的shell,每个用户的缺省shell在系统里的/etc/passwd文件里被指定。

写一个简易的shell需要以下操作:

  1. 获取命令行
  2. 解析命令行(strtok:将字符串打散)
  3. 建立一个子进程(fork)
  4. 替换子进程(execve)
  5. 父进程等待子进程(wait)

代码实现:

#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<string.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<ctype.h>
#include<fcntl.h>

int main()
{
        while(1)
        {
                printf("[Myshell]>");
                fflush(stdout);
                //解析输入到shell上的字符串 ls   -a -l
                char buffer[1024];
                int read_size = read(1, buffer, sizeof(buffer)-1);
                if (read_size > 0)
                {
                        buffer[read_size - 1] = 0;
                }
                char* shell_argv[32] = {NULL};
                int shell_index = 0;
                char* start = buffer;
                while (*start != '\0')
                {
                        while (*start != '\0' && isspace(*start))
                        {
                                start++;
                        }
                }

                //创建子进程来exec

                pid_t pid = vfork();

                if (pid < 0)
                {
                        printf("vfork failure\n");
                        exit(1);
                }
                else if (pid == 0)
                {
                //考虑重定向 > 
                //在字符串数组中找重定向标志
                        int i = 0;
                        int flag = 0;
                        for (; shell_argv[i] != NULL; ++i )
                        {
                                if (strcmp(">", shell_argv[i]) == 0)
                                {
                                        flag = 1;
                                        break;
                                }
                        }

                        int copyFd;
                        shell_argv[i] = NULL;
                        if (flag)
                        {
                                if (shell_argv[i+1] == NULL)
                                {
                                        printf("command error\n");
                                        exit(1);
                                }
                                close(1);
                                int fd = open(shell_argv[i+1], O_WRONLY | O_CREAT, 0777
);
                                copyFd = dup2(1, fd);
                        }
                        execvp(shell_argv[0], shell_argv);
                        if (flag)
                        {
                                close(1);
                                dup2(copyFd, 1);
                        }
                        exit(1);
                }
                else //father process
                {
                        int status = 0;
                        int ret = waitpid(pid, &status, 0);
                        if (ret == pid)
                        {
                                if (WIFEXITED(status))
                                {
                                        // printf("exitCode is %d\n", WEXITSTATUS(statu
s));
                                }
                                else if (WIFSIGNALED(status))
                                {
                                        printf("signal is %d\n", WTERMSIG(status));
                                }
                        }
                }
        }
        return 0;
}

猜你喜欢

转载自blog.csdn.net/Jochebed666/article/details/83510733