Linux中的进程替换
目录
进程替换
替换函数
execl
execlp
execv
execvp
execle
简单的命令行解释器
对cd命令进行特殊处理
echo$?
进程替换
创建子进程的目的?
a.让子进程执行父进程代码的一部分->执行父进程对应的磁盘代码的一部分
b.让子进程执行一个全新的程序->让子进程,加载磁盘上指定的程序,执行新的代码和数据(进程程序替换)
替换函数
#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[])
给所有的exec*系列函数传参时,最后一个必须为NULL
execl
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("process is running...\n");
execl("/usr/bin/ls","ls","-a","-l",NULL);
printf("process is running...\n");
}
运行myexe等价于执行ls命令。
为什么printf没有被打印?
printf位于exec之后,当execl执行完成之后,代码已经被覆盖,并开始执行新的程序和代码了,所以printf无法执行。
及如果execl发生了返回,意味着execl函数调用失败。
程序替换时代码可能发生写时拷贝。
虚拟地址空间+页表可以保证进程独立性。
一旦有执行流想替换代码或数据就会发生写时拷贝。
execlp
execlp("ls","ls","-a","-l",NULL);
第一个ls是指明要执行的程序
第二个ls是告诉系统要如何执行
execv
char* const argv[]={
"ls",
"-a",
"-l",
NULL
};
execv("/usr/bin/ls",argv);
execvp
char* const argv[]={
"ls",
"-a",
"-l",
NULL
};
execvp("ls",argv);
makefile默认只能形成一个可执行程序,从上往下扫描先根据第一个目标文件,形成目标对象。
#!/bin/bash
echo "hello shell"
echo "hello shell"
execl("./myshell","myshell.sh","-a","-l",NULL);
execle
exec*系列的函数可以将程序加载到内存中,在Linux中加载的方式为通过exec*加载(加载器)
只有execve是系统调用。
字符串切割:strtok,strtok读到NULL时结束。
简单的命令行解释器
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<sys/types.h>
#include<sys/wait.h>
#define NUM 1024
#define OPT_NUM 64
char lineCommand[NUM];
char* myargv[OPT_NUM];
int main()
{
while (1)
{
printf("用户名@主机名# ");
fflush(stdout);
// 获取用户输入
char *s = fgets(lineCommand, sizeof(lineCommand) - 1, stdin);
assert(s != NULL);
lineCommand[strlen(lineCommand) - 1] = 0;
myargv[0]=strtok(lineCommand," ");
//"la -a -l"
int i = 1;
while (myargv[i++] = strtok(NULL, " "));
pid_t id=fork();
assert(id!=-1);
if(id==0)
{
execvp(myargv[0],myargv);
exit(1);
}
waitpid(id,NULL,0);
}
return 0;
}
对cd命令进行特殊处理
if(myargv[0]!=NULL&&strcmp(myargv[0],"cd")==0)
{
if(myargv[1]!=NULL) chdir(myargv[1]);
continue;
}
向cd这种不需要子进程执行,而是让shell自己执行的命令称为内建/内置命令。
内建/内置命令
及shell内部的一个函数
echo$?
if(myargv[0]!=NULL&&myargv[1]!=NULL&&strcmp(myargv[0],"echo"))
{
if(strcmp(myargv[1],"$?"))
{
printf("%d,%d\n",lastCode,lastSig);
}
else
{
printf("%s\n",myargv[1]);
}
continue;
}
查看最近一个进程的退出码。