目录
1.进程替换的概念
我们都明白在创建子进程的时候,子进程会和父进程共用代码。那么如果我们想给子进程单独的代码我们要做什么呢?答案是:我们需要通过调用一些系统接口将子进程替换成新的程序对应的进程。逻辑上就是先将新程序加载入物理内存,再将子进程所对应的页表指向换成该新程序,从而实现进程替换。
2.了解几个进程替换的接口
a.execl(const char* path,const char* argv,......)
path:新程序的路径
argv:指令,例如"ls"
......:选项,例如'-a' '-l'
如果我们就是想通过进程替换实现ls,实现方法:
1 #include<stdio.h>
2 #include<unistd.h>
3
4
5 int main()
6 {
7 execl("/usr/bin/ls","ls","-a","-l",NULL);
8 return 0;
9 }
结果如下:
通过进程替换成功实现了ls指令。
b.execlp(const char* file,const char* argv,......)
和execl相比,只是会从path直接找指令,可以直接输入指令名称而非路径。
c.execv(const char* path,const char* argv[])
和execl相比,只是将输入的字符用字符指针数组传入。
d.excvp(const char* file,const char* argv[])
不详细解释了。
3.自己模拟实现一个shell
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#define NUM 1024
#define SIZE 24
#define EP " "
char cmd_line[NUM];
char *g_argv[SIZE];
int main()
{
while(1)
{
printf("[root@localhost myshell]# ");
fflush(stdout);
memset(cmd_line,'\0',sizeof(cmd_line));
if(fgets(cmd_line,sizeof(cmd_line),stdin)==NULL)
{
continue;
}
//清除\n
cmd_line[strlen(cmd_line)-1]='\0';
//将输入指令打散 例如 "ls -a -l" -> "ls" "-a" "-l"
g_argv[0]=strtok(cmd_line,EP);
int index = 1;
//美观特殊处理
if(strcmp(g_argv[0], "ls") == 0)
{
g_argv[index++] = "--color=auto";
}
if(strcmp(g_argv[0], "ll") == 0)
{
g_argv[0] = "ls";
g_argv[index++] = "-l";
g_argv[index++] = "--color=auto";
}
while(g_argv[index++]=strtok(NULL,EP));
if(strcmp(g_argv[0], "cd") == 0) //cd 是shell库的函数,内置指令直接调用.
{
if(g_argv[1] != NULL)
chdir(g_argv[1]); //cd path, cd ..
continue;
}
pid_t id = fork();
if(id == 0)
{
printf("下面功能让子进程进行的\n");
execvp(g_argv[0], g_argv);
exit(1);
}
int status=0;
pid_t ret=waitpid(id,&status,0);
if(ret > 0) printf("exit code: %d\n", WEXITSTATUS(status));
}
return 0;
}
结果如下:
如图所示, 运行myshell后,我们就像正常在shell中使用指令一样。但是还没有实现一些shell库独有的指令,不过基本的都包含在内。