shell是什么?

维基百科:Unix shell也叫做命令行界面,它是Unix操作系统下传统的用户和计算机的交互界面。用户直接输入命令来执行各种各样的任务。

现在的shell不止这些功能,不过,这些与本文无关。

shell中命令的执行过程?

启动shell,本身就是创建一个进程。在shell中运行命令的时候,shell进程会以自己为模板,创建(fork)一个新的进程。这个新建的进程对shell中输入的命令进行处理,处理完之后新进程结束自己的生命,等待shell进程进行回收。具体来说,就是:

  1. shell进程调用fork()这一系统调用来创建了一个子进程。
  2. 父进程(也就是shell进程)调用wait()这一系统调用后进行等待,直到新建的子进程结束。
  3. 子进程调用exec()这一系统调用来执行shell中输入的命令,执行完成后,调用exit()这一系统调用来结束生命。
  4. 父进程的wait()回收信息,释放子进程的PCB,彻底销毁子进程。

shell是如何实现的?

下面是《Unix/Linux编程实践教程》中的代码。

#define MAXARGS 20 
#define ARGLEN 100 

main()
{
    char *arglist[MAXARGS+1];
    int numargs; 
    char argbuf[ARGLEN]; 
    char *makestring();

    numargs = 0;
    while ( numargs < MAXARGS )
    {
        printf("Arg[%d]? ", numargs);
        if ( fgets(argbuf, ARGLEN, stdin) && *argbuf != '\n' )
            arglist[numargs++] = makestring(argbuf);
        else
        {
            if ( numargs > 0 ){ 
                arglist[numargs]=NULL; 
                execute( arglist ); 
                numargs = 0; 
                }
        }
    }
    return 0;
}

execute( char *arglist[] )
{
    int pid,exitstatus;

    pid = fork(); //在这里,shell就有了自己的分身,也就是子进程(这里可以看作内存中运行了2个相同的进程)。
    switch( pid ){
        case -1:
            perror("fork failed");
            exit(1);
        case 0:
            execvp(arglist[0], arglist); //如果PID是0,说明是子进程,运行新的命令(新的shell有了新的思想)。
            perror("execvp failed");
            exit(1);
        default:
            while( wait(&exitstatus) != pid )//父进程shell等待子进程结束,并获取信息。
                ;
            printf("child exited with status %d,%d\n",
            exitstatus>>8, exitstatus&0377);
    }
}

char *makestring( char *buf )
{
    char *cp, *malloc();

    buf[strlen(buf)-1] = '\0';
    cp = malloc( strlen(buf)+1 ); 
    if ( cp == NULL ){ 
        fprintf(stderr,"no memory\n");
        exit(1);
    }
    strcpy(cp, buf); 
    return cp; 
}

刚学习fork时候,一直把父子进程看作一个程序,只是在理论上知道fork是复制了一个自己,通过上面的程序终于对fork有了一个较为清晰的认识。就好比一个懒人自己总不想做事,想要学会分身术,让分身去做事。在linux中这个懒人就是init进程,它复制了很多自己来为它做事,这些孩子们遗传了它的个性,也喜欢复制自己去做事,这就是linux系统中的一个个进程。