当前位置: 首页 > article >正文

我与Linux的爱恋:进程程序替换


外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

🔥个人主页guoguoqiang. 🔥专栏Linux的学习

Alt

文章目录

  • ​进程程序替换
    • 替换函数
    • 替换原理
    • 多进程替换
    • exec*函数使用
    • 替换函数总结

​进程程序替换

替换函数

有六种以exec开头的函数,统称exec函数。
在这里插入图片描述

#include <stdio.h>
#include <unistd.h>

int main(){
    printf("testexec ...begin!\n");
    execl("/usr/bin/ls","ls","-a","-l",NULL);
    printf("testexec ...end!\n");
    return 0;
}

在这里插入图片描述
execl被ls替换了,替换也是完完全全的,不会执行后面的代码。

替换原理

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

在这里插入图片描述
站在被替换进程的角度:本质就是这个程序被加载到内存中了;通过exec*加载函数。

多进程替换

fork创建子进程,让自进程自己去替换
创建子进程的目的是让子进程完成任务:1.让子进程执行父进程代码的一部分 2.让子进程执行一个新的程序

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
    printf("testexec ...begin!\n");
    pid_t id=fork();
    if(id==0){
        printf("child pid: %d\n",getpid());
        sleep(2);
        execl("/usr/bin/ls","ls","-a","-l",NULL);
        exit(1);
    }
    //father
    int status=0;
    pid_t rid=waitpid(id,&status,0);
    if(rid>0){
        printf("father wait success,child exit code :%d \n",WEXITSTATUS(status));
    }
    printf("testexec ...end!\n");
    return 0;
}

在这里插入图片描述
在这里插入图片描述
即使是父子也要保证独立性,以前是父子共享一块空间,需要时时对数据段进行写实拷贝,现在是完完全全开辟新的空间,保证进程的独立性。

exec*函数使用

1.execl
函数原型,在前面我们已经使用过了,这里不过多介绍。关于exec*函数,我们不考虑它的返回值

int execl(const char *path, const char *arg, ...);

这里的 l 可以理解为list,path传入绝对路径,arg可变参数,依次传入命令,以及你想执行的指令,最后一个必须为NULL
2.execv
函数原型:

int execv(const char *path, char *const argv[]);

这里的v可以理解为vector,argv是一个指针数组,我们可以直接来使用

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
    printf("testexec ...begin!\n");
    pid_t id=fork();
    if(id==0){
        printf("child pid: %d\n",getpid());
        sleep(2);
        char *const argv[]={
            (char*)"ls",
            (char*)"-l",
            (char*)"-a",
            (char*)"--color",
            NULL
        };
        execv("/usr/bin/ls",argv);
        exit(1);
    }
    //father
    int status=0;
    pid_t rid=waitpid(id,&status,0);
    if(rid>0){
        printf("father wait success,child exit code :%d \n",WEXITSTATUS(status));
    }
    printf("testexec ...end!\n");
    return 0;
}

在这里插入图片描述
3.execvp
函数原型:

int execvp(const char *file, char *const argv[]);

用户可以不传要执行的文件的路径(但是文件名要传),直接告诉exec*,我要执行谁都行
p:查找这个程序,系统会自动在环境变量PATH中进行查找

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
    printf("testexec ...begin!\n");
    pid_t id=fork();
    if(id==0){
        printf("child pid: %d\n",getpid());
        sleep(2);
        char *const argv[]={
            (char*)"ls",
            (char*)"-l",
            (char*)"-a",
            (char*)"--color",
            NULL
        };
        execvp("ls",argv);
        exit(1);
    }
    //father
    int status=0;
    pid_t rid=waitpid(id,&status,0);
    if(rid>0){
        printf("father wait success,child exit code :%d \n",WEXITSTATUS(status));
    }
    printf("testexec ...end!\n");
    return 0;
}

在这里插入图片描述
4.execvpe
函数原型:

 int execvpe(const char *file, char *const argv[],char *const envp[]);
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
    printf("testexec ...begin!\n");
    pid_t id=fork();
    if(id==0){
        printf("child pid: %d\n",getpid());
        sleep(2);
        char *const argv[]={
            (char*)"ls",
            (char*)"-a",
            (char*)"-l",
            (char*)"--color",
            NULL
        };

        extern char** environ;
        execvpe("ls",argv,environ);
        exit(1);
        //execl("/usr/bin/ls","ls","-a","-l",NULL);
        //execv("/usr/bin/ls",argv);
        //execvp("ls",argv);
    }
    //father
    int status=0;
    pid_t rid=waitpid(id,&status,0);
    if(rid>0){
        printf("father wait success,child exit code :%d \n",WEXITSTATUS(status));
    }
    printf("testexec ...end!\n");
    return 0;
}

在这里插入图片描述
execlp和execlpe
方法与上面相同。

替换函数总结

在这里插入图片描述
这些函数之间的关系如下图所示
在这里插入图片描述

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
    printf("testexec ...begin!\n");
    pid_t id=fork();
    if(id==0){
        putenv("AAAA=11111232154");
         // 我的父进程本身就有一批环境变量!!!, 从bash来
        printf("child pid: %d\n",getpid());
        sleep(2);
        char *const argv[]={
            (char*)"ls",
            (char*)"-a",
            (char*)"-l",
            (char*)"--color",
            NULL
        };

        extern char** environ;
       // execvpe("ls",argv,environ);
        //exit(1);
        //execl("/usr/bin/ls","ls","-a","-l",NULL);
        //execv("/usr/bin/ls",argv);
        //execvp("ls",argv);
        execl("/usr/bin/python3","python3","test.py",NULL);
    }
    //father
    int status=0;
    pid_t rid=waitpid(id,&status,0);
    if(rid>0){
        printf("father wait success,child exit code :%d \n",WEXITSTATUS(status));
    }
    printf("testexec ...end!\n");
    return 0;
}
print("hello python")
print("hello python")
print("hello python")
print("hello python")
print("hello python")
print("hello python")

在这里插入图片描述


http://www.kler.cn/news/368099.html

相关文章:

  • 环回地址和本地地址有什么区别
  • 2024 7月算法刷题记录
  • Java进阶篇设计模式之二 ----- 工厂模式
  • Linux: Shell编程入门
  • 【数学二】多元函数积分学-重积分-二重积分定义、性质、计算
  • ALIGN_ Tuning Multi-mode Token-level Prompt Alignment across Modalities
  • 版本工具报错:Error Unity Version Control
  • ArkTS 如何适配手机和平板,展示不同的 Tabs 页签
  • 「AIGC」AI设计工具 v0.dev
  • Webpack优化项⽬的⼿段
  • 【网络安全初识】——互联网发展史
  • PHP 中的 die () 和 exit () 函数有什么不同
  • 计算机mfc100.dll丢失的五种有效解决方法,快速解决dll文件-常见问题
  • 2024年Java面试:必备的易错面试题及答案整理
  • Linux基础知识 - C(自学使用)
  • Unity 开发学习笔记(0):
  • Kafka 解决消息丢失、乱序与重复消费
  • 面向对象编程中类与类之间的关系(一)
  • 草地杂草数据集野外草地数据集田间野草数据集YOLO格式VOC格式目标检测计算机视觉数据集
  • 鸿蒙网络编程系列32-基于拦截器的性能监控示例
  • unity中GameObject介绍
  • unity 导入的模型设置详谈
  • 【ShuQiHere】Linux 系统中的硬盘管理详解:命令与技巧
  • C++ | Leetcode C++题解之 第508题出现次数最多的子树元素和
  • Day 53 图论五
  • nginx 修改配置