Linux进程控制—02
1.程序替换
程序替换本质来说就是替换一个pcb在内存中对应的代码和数据。加载另一个程序到内存中,然后更新页表信息,初始化虚拟地址空间。这个进程pcb将从头重新开始调度新的程序运行。
程序替换函数族
int execl(const char* path, const char* arg, ...);
int execlp(const char* flie, 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 execve(const char* file, char* const argv[], char* const envp[]);
函数的使用
test.c:
#include<stdio.h>
int main(int argc, char* argv[], char* env[])
{
int i;
for(i = 0;argc[i] != NULL;i++)
{
printf("argv[%d] = %s\n", i, argv[i]);
}
for(i = 0;env[i] != NULL;i++)
{
printf("env[%d] = %s\n", i, env[i]);
}
return 0;
}
主文件:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main(int argc, char* argv[], char* env[])
{
execl("./test", "test", "-l", NULL);
//会去调用当前路径下的test程序,输入参数为test和-l
char* new_argv[] = {"test", "-L", "-P", NULL};
execv("./test", new_argv);
//会去调用当前路径下的test程序,输入参数为该指针数组的内容
execvp("test", new_argv);
//如果在PATH环境变量下指定了路径,使用这个函数则可以不用带路径
char* new_env[] = {"MYVAL=10","TESTVAL=20",NULL};
execve("./test", new_argv, new_env);
//会去调用当前路径下的test程序,输入参数为该指针数组内容,同时将设定的环境变量传入。
return 0;
}
l和v的区别:在于程序运行参数的赋予方式不同,l通过不定参完成/v通过字符串指针数组赋予
有没有p的区别:在于第一个参数执行程序的时候,是否需要带路径,有p则可以不用带路径,默认会去PATH环境变量指定的路径下查找。
有没有e的区别:在于这个进程的环境变量舒服需要程序初始化。有e则表示初始化,没有则表示使用默认的环境变量。通过execve我们能够明白,一个进程的环境变量实际上是他的父进程赋予的。
2.minishell程序
我们在终端中运行一个程序,这个程序的父进程实际上是shell程序。当我们在shell中输入了一个命令,这时候其实shell对这个标准输入进行解析,得到了程序名称,然后创建子进程,并且将子进程的程序替换为当前这个解析出来的程序。
下面我们自己实现一个minishell程序,来体会整个进程控制过程。
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
int main()
{
umask(0);
while(1)
{
printf("[sw@minishell]$ ");
fflush(stdout);//刷新标准输出缓冲区
//等待标准输入
char buf[1024] = {0};
fgets(buf, 1023, stdin);
buf[strlen(buf) - 1] = '\0';
//对标准输入进行解析
char* ptr = buf;
char* argv[32] = {NULL};
int argc = 0;
while(*ptr != '\0')
{
if(*ptr != ' ')
{
argv[argc] = ptr;
argc++;
while(*ptr !=' ' && *ptr != '\0')
{
ptr++;
}
*ptr = '\0';
}
ptr++;
}
argv[argc] = NULL;
//创建子进程
pid_t pid = fork();
if(pid == 0)
{
//子进程中进行程序替换
execvp(argv[0], argv);
exit(0);
}
//父进程进程等待子进程退出
wait(NULL);
}
return 0;
}