Linux进程控制(进程替换)
创始人
2024-05-13 21:28:06
0

目录

一、进程程序替换原理

 二、进程替换函数

三、函数实现子进程进程替换

3.1 测试函数

3.2 写时拷贝保证替换后的进程独立性

四、自我实现一个简单的 shell

五、内置命令

5.1 pwd查询路径本质

5.2 内置命令概念

5.3 自我实现shell Pro


 先见见进程替换:

#include
#includeint main()
{printf("the process is running...\n");execl("/usr/bin/ls","ls","--color=auto",NULL);//进程替换
}


一、进程程序替换原理

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变!


 二、进程替换函数


系统调用接口:

函数封装接口:

#include `
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[]);

l(list) : 表示参数采用列表
v(vector) : 参数用数组
p(path) : 有p自动搜索环境变量PATH
e(env) : 表示自己维护环境变量

可变参数:

 我们发现每个函数参数表中都有...,这代表着我们的参数列表是可变参数列表!

可变参数列表允许参数个数是动态的,想传多少就传多少,最后以NULL结尾!我们原来用的printf函数也是典型的可变参数!


三、函数实现子进程进程替换

3.1 测试函数

#include
#include
#include
#include
#include
int main()
{pid_t id=fork();if(id==0){printf("the child process is running...\n");printf("我是子进程,id=%d\n",getpid());sleep(1);//法一:execl 列表传命令//execl("/usr/bin/ls","ls","--color=auto",NULL);//系统命令//execl("./mybin","mybin",NULL);//自己编写的程序//法二:execlp 环境变量PATH//execlp("ls","ls","--color=auto",NULL);//法三:execv 数组传命令//  char* const _argv[]={//     "ls",//     "-a",//     "-l",//     "--color=auto",//     NULL// };//execv("/usr/bin/ls",_argv);//法四:execvp 二和三的组合//  char* const _argv[]={//     "ls",//     "-a",//     "-l",//     "--color=auto",//     NULL// };// execvp("ls",_argv);//法五:execle 获取环境变量extern char**environ;char* const _envp[]={"myval=666",NULL};putenv("myval=666");//自己设置环境变量execle("./mybin","mybin",NULL,environ);exit(-1);//进程替换失败}else if(id>0){int status=0;pid_t ret=waitpid(id,&status,0);sleep(3);if(ret>0)printf("wait success:%d  sig code=%d  child exit code=%d\n",ret,status&0X7F,(status>>8)&0XFFFF);}else{printf("creat child process error!\n");}return 0;
}

法四结果:


法五结果:


3.2 写时拷贝保证替换后的进程独立性

💡💡

子进程程序替换前共享父进程代码!程序替换会将磁盘代码替换原代码!进程具有独立性,子进程不能直接替换共享代码而影响父进程!所以操作系统会对子进程代码进行写时拷贝!


四、自我实现一个简单的 shell

#include
#include
#include
#include
#include
#include
#include
#define NUM_SIEZ 1024
char Command_Line[NUM_SIEZ];
#define OPT_NUM 64
char* myargv[OPT_NUM];
#define DEBUG
int main()
{
while(1)
{printf("[用户名@主机名  当前路径]$ ");fflush(stdout);//刷新缓冲区char* str=fgets(Command_Line,sizeof(Command_Line)-1,stdin);//从标准输入获取字符串assert(str!=NULL);//"abcde\n" 让最后一个字符为NULL(0)!为后面命令数组结尾获取0!Command_Line[strlen(Command_Line)-1]=0;
#ifdef DEBUG//以空格为分隔单位,获取命令与命令选项!myargv[0]=strtok(Command_Line," ");int i=1;while(myargv[i++]=strtok(NULL," "));
#endif//创建子进程pid_t id=fork();if(id==0)//子进程程序替换{execvp(myargv[0],myargv);exit(1);//进程替换失败}else if(id>0)//父进程等待{waitpid(id,NULL,0);}else{printf("creat child process error!\n");}
}      return 0;
}


五、内置命令

问题引入:下面我们来看一看自我实现的shell 实现下面的命令:

 


5.1 pwd查询路径本质


 进程路径是可以被修改的,磁盘路径是亘古不变的!,pwd的本质是查询当前进程的工作目录!我们可以通过chdir修改工作路径!


 5.2 内置命令概念

内置命令指的是命令由父进程本身执行,不靠子进程程序替换的命令!例如 echo pwd 命令!


5.3 自我实现shell Pro

#include
#include
#include
#include
#include
#include
#include
#define NUM_SIEZ 1024
char Command_Line[NUM_SIEZ];
#define OPT_NUM 64
char* myargv[OPT_NUM];
//子进程返回结果
int last_sigcode=0;
int last_exit_code=0;
int main()
{
while(1)
{printf("[用户名@主机名  当前路径]$ ");fflush(stdout);char* str=fgets(Command_Line,sizeof(Command_Line)-1,stdin);//从标准输入获取字符串assert(str!=NULL);//"abcde\n" 让最后一个字符为NULL(0)!为后面命令数组结尾获取0!Command_Line[strlen(Command_Line)-1]=0;//以空格为分隔单位,获取命令与命令选项!myargv[0]=strtok(Command_Line," ");int i=1;//文件带上标识颜色if(strcmp(myargv[0],"ls")==0){myargv[i++]="--color=auto";}while(myargv[i++]=strtok(NULL," "));if(myargv[0]!=NULL && myargv[1]!=NULL && strcmp(myargv[0],"cd")==0){chdir(myargv[1]);//改变父进程程序路径continue;//内置命令,直接结束}if(myargv[0]!=NULL && myargv[1]!=NULL && strcmp(myargv[0],"echo")==0){if(strcmp(myargv[1],"$?")==0)//获取上一次进程结果{printf("sigcode=%d exit_code=%d\n",last_sigcode,last_exit_code);continue;}else{printf("%s\n",myargv[1]);last_exit_code=0;last_sigcode=0;continue;}}//创建子进程pid_t id=fork();if(id==0){execvp(myargv[0],myargv);exit(1);//进程替换失败}else if(id>0){int status=0;int ret=waitpid(id,&status,0);assert(ret>0);last_sigcode=status&0X7F;last_exit_code=(status>>8)&0XFF;}else{printf("creat child process error!\n");}
}      return 0;
}


相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...