思路:先创建一个父进程,然后在父进程中创建一个子进程,而在子进程中调用exec函数族,父进程所要做的只是等待子进程的结束,然后再次循环等待用户输入下一条命令。注:因为要模拟的是bash,所以在一条命令执行完成了后,执行命令的进程结束了,但是bash并没有结束(即不能在父进程中调用exec函数族,否则父进程也会结束,不符合实际),而是等待刚才输入的命令结束后,再次提示用户输入下一条命令,直到用户输入了exit为止。

代码:

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

#define N 64

int main(int argc, char *argv[])
{
    char buf[N] = {0};   //定义并初始化一个字符串数组
    char *arg[N];     //定义一个指针数组
    pid_t pid;
    int i = 0, j;

    while (1)
    {
        printf("linux@ubuntu:~$");
        fgets(buf, N, stdin);//ls -l -a   //等待用户从键盘输入,回车后将输入的内容写到buf,包括 \n,
										  //此时,buf数组中以\0结尾,\0 前面是 \n,显然 \n 不是命令
        buf[strlen(buf)-1] = '\0';        //将buf数组中的\0前面的那个\n用\0进行覆盖
        if (strcmp(buf, "exit") == 0)     //看输入的是否为exit,注:没有对空格进行处理
            break;

        if ((pid = fork()) == -1)         //创建子进程
        {
            perror("fork");
            exit(-1);
        }
        if (pid == 0)
        {
		/*
			下面是利用strtok函数将buf数值进行解析,把命令和参数分别解析出来,strtok函数的使用参见
			C语言函数大全:下面是部分内容
			头文件:#include <string.h>

			定义函数:char * strtok(char *s, const char *delim);

			函数说明:strtok()用来将字符串分割成一个个片段. 参数s 指向欲分割的字符串, 参数delim 则为分割字符串,当strtok()在参数s 的字符串中发现到参数delim 的分割字符时则会将该字符改为\0 字符. 在第一次调用时,strtok()必需给予参数s 字符串, 往后的调用则将参数s 设置成NULL. 每次调用成功则返回下一个分割后的字符串指针.

			返回值:返回下一个分割后的字符串指针, 如果已无从分割则返回NULL.

			范例
			#include <string.h>
			#include <stdio.h>
			int main(void)
			{
				char s[] = "ab-cd : ef;gh :i-jkl;mnop;qrs-tu: vwx-y;z";
				char *delim = "-: ";
				char *p;
				printf("%s ", strtok(s, delim));
				while((p = strtok(NULL, delim)))
					printf("%s ", p);
				printf("\n");
				return 0;
			}
			执行结果:
			ab cd ef;gh i jkl;mnop;qrs tu vwx y;z //-与:字符已经被\0 字符取代

		*/
            arg[i] = strtok(buf, " ");      
            do
            {
                ++i;
                arg[i] = strtok(NULL, " ");
            }while(arg[i] != NULL);

            for (j = 0; j < i; j++)
                printf("%s\n", arg[j]);

        //    char * arg[] = {"ls", "-l", "-a", NULL};
            if (-1 == execvp(arg[0], arg)) //在子进程中调用execvp函数,子进程的三段被替换
            {
                perror("execvp");
                exit(-1);
            }
        }
        else
            wait(NULL);  //父进程等待子进程就是,即等待argv[0]中指向的命令执行完
    }

    return 0;
}