进程程序替换
使用fork创建进程后,子进程与父进程执行相同的代码程序(有可能执行不同的代码分支)。
子进程通过调用一种exec函数,执行另一个程序。当进程调用一种exec函数时,该子进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。
调用exec函数并不创建新进程,所以exec调用前后进程的id没有发生改变
替换函数
六种以exec开头的函数统称为exec函数
#include <unistd.h>
参数采用列表形式
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
参数采用数组形式
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);
- [ l ] :表示参数采用列表形式
- [ v ] :表示参数采用数组形式
- [ p ] :有p自动搜索环境变量
- [ e ] :表示自己维护环境变量
如果这些函数调用成功,则加载的新的程序从启动代码开始执行,不再返回。如果调用失败则返回-1. 所以exec函数只有出错的返回值没有成功的返回值
exec调用举例
#include <unistd.h>
int main()
{
char* const argv[]={"ls","-a","NULL"};
char* const envp[]={"PATH=/bin:/user/bin","NULL"};
execl("/bin/ls","ls","-a","NULL");
execlp("ls","ls","-a","NULL");
//带p的,可以使用环境变量PATH,不需要写全路径
execle("/bin/ls","ls","-a","NULL",envp);
//带e的,需要自己组装环境变量,写全路径
execv("/bin/ls",argv);
execvp("ls",argv);
execve("/bin/ls",argv,envp);
}
只有execve函数是正真的系统调用,其他五个函数都将调用execve函数
使用程序替换实现简易的shell
通过将我们输入的字符串解析,进行通过进程创建和进程的替换,简单模拟shell的运行
输入命令-》解析字符-》创建子进程-》程序替换-》退出
将其放入循环中即可实现简单的shell操作
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <sys/wait.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7
8 int main()
9 {
10
11 char cmd[1024];
12 char* myargv[16];
13
14 while(1){
15
16 printf("[wens@localhost myshell]# ");
17
18 fgets(cmd,sizeof(cmd),stdin);
19
20 int i=0;
21
22 cmd[strlen(cmd)-1]='\0'; 23
24 myargv[i++]=strtok(cmd," ");//将字符串分割解析
25
26 char *ret=NULL;
27
W> 28 while(ret=strtok(NULL," "))
29 {
30 myargv[i++]=ret;
31 }
32
33 myargv[i]=NULL;
W> 34 int j=0;
35 // for( j=0;j<i;j++)
36 //boot printf("%s\n",myargv[j]);
37
38
39
40 pid_t id=fork();
41 if(id==0)
42 {
43 execvp(myargv[0],myargv); //进行程序替换
44 exit(1);
45 }else{
46 waitpid(id,NULL,0); //等待子进程
47 }
48 }
49 return 0;
50
51
52
53 }
~