Linux之进程控制(下)

news/2024/10/5 10:54:03/

目录

进程替换的概念

进程替换的函数

execl​编辑

execlp

execle

 execv

execvp

execve


上期,我们学习了进程创建,进程终止和进程等待,今天我们要学习的是进程控制中相对重要的板块------进程替换。

进程替换的概念

在进程创建时,我们使用了fork函数创建了子进程。但是大家仔细回想一下,其实在子进程创建之后,父子进程共享的是同一代码,可以理解为子进程执行的是父进程代码的一部分,有没有什么办法可以让子进程不去执行父进程的代码,而去执行一份新的代码呢?进程替换就是其中的方法之一。

进程替换:进程替换是指替换到原有进程的代码,但是原有的进程的数据结构不变的技术,就叫做进程替换。

替换原理图示如下。

 由图示可见,进程替换其实是没有新进程的创建的,只是更改了之前进程代码以及虚拟地址空间和页表之间的对应关系。所以进程替换的代价相对而言是比较小的。

进程替换的函数

进程替换主要要用到exec类的函数,用于去执行另一个程序的代码。exec函数主要有六个,我们一一来解释。

execl

参数:第一个参数为要执行的命令的路径,第二个参数为命令行参数,即命令要执行什么,但是最终必须以NULL结尾,不然会出错。

先看下述代码。

这是一个简单的打印程序。运行结果如下:

然后使用execl函数进行替换。

#include<stdio.h>
#include<unistd.h>int main()
{printf("process begin\n");execl("/usr/bin/ls","ls","-a","-l",NULL);printf("process end\n");return 0;
}

运行结果如下。

我们惊奇的发现,"process end"字符串没有打印,这是为什么呢?

原因就是在进行进程替换之后,当前进程的所有代码都被进行了替换,之前的和之后的代码都被进行了替换,所以替换之后的代码自然没有被执行,所以自然没有打印对应的语句。 

execlp

参数列表:第一个参数为要执行的命令的名称,第二个参数为命令函参数,与execl要求类似。

 代码如下。

#include<stdio.h>
#include<unistd.h>int main()
{printf("process begin\n");execlp("ls","ls","-a","-l",NULL);printf("process end\n");return 0;
}

运行结果如下。

我们发现运行结果也符合我们的预期。

execle

参数列表:第一个参数为命令的路径,第二个参数为命令行参数与execl类似,第三个参数为环境变量参数。 

代码如下。

#include<stdio.h>
#include<unistd.h>int main()
{printf("process begin\n");char *env[]={"hello world","hello world","hello yjd"};execle("/usr/bin/ls","ls","-a","-l",NULL,env);printf("process end\n");return 0;
}

运行结果如下。

运行结果符合预期。

 execv

 

参数列表:第一个参数为命令的路径,第二个参数为命令行参数组成的一个指针数组。

代码如下。

#include<stdio.h>
#include<unistd.h>int main()
{printf("process begin\n");char* const argv[]={"ls","-a","-l",NULL};execv("/usr/bin/ls",argv);printf("process end\n");return 0;
}

 运行结果如下。

运行结果符合预期。

execvp

参数列表:第一个参数为命令名称,第二个参数为命令行参数组成的指针数组。

代码如下。

#include<stdio.h>
#include<unistd.h>int main()
{printf("process begin\n");char* const argv[]={"ls","-a","-l",NULL};execvp("ls",argv);printf("process end\n");return 0;
}

运行结果如下。

运行结果符合预期。

execve

 这个接口是系统调用接口,其它六个exec类函数都是库函数接口,证明其它六个exec函数与execve函数肯定是有关系的,具体什么关系我们等下再去讨论。

参数列表:第一个参数为命令路径,第二个参数为命令行参数组成的指针数组,第三个参数为环境变量组成的指针数组。 

代码如下。

#include<stdio.h>
#include<unistd.h>int main()
{printf("process begin\n");char* const env[]={"hello world","hello world","hello yjd",NULL};char* const argv[]={"ls","-a","-l",NULL};execve("/usr/bin/ls",argv,env);printf("process end\n");return 0;
}

运行结果如下。

运行结果如何预期。

回到刚开始的问题execve函数与其它几个函数有什么区别呢?

可以理解为除过execve函数之外的其它函数的本质都是execve函数,因为execve函数是系统调用接口,而除execve之外的其它函数都是第三方库的接口,我们知道库函数的实现本质上是系统调用函数的实现。

以上便是本期进程替换的所有内容,到了这里进程控制的所有内容已经全部学习完毕。

本期内容到此结束^_^

 

 


http://www.ppmy.cn/news/1473593.html

相关文章

【数据结构】03.顺序表的应用——通讯录

本篇文章我们将使用顺序表来实现通讯录的增删查改功能。 代码如下&#xff1a; //Contact.h#pragma once#define NAME_MAX 30 #define GENDER_MAX 10 #define ADDRESS_MAX 100 #define TEL_MAX 12enum{Exit,Add,Del,Seek,Change,Show};//枚举类型&#xff0c;便于理解数字含义…

线程同步66666

1. 概述 当有多个线程访问同一个共享资源&#xff08;临界资源&#xff09;时&#xff0c;且不允许同时访问&#xff0c;那么就需要线程同步。常见的线程同步方式&#xff1a;互斥锁、读写锁、条件变量、信号量。 2. 互斥锁 互斥锁的方式可以简单概括为&#xff1a;锁定操作…

Jenkins教程-13-参数化任务构建

上一小节我们学习了发送html邮件测试报告的方法&#xff0c;本小节我们讲解一下Jenkins参数化任务构建的方法。 很多时候我们需要根据不同的条件去执行构建&#xff0c;如自动化测试中执行test、stg、prod环境的构建&#xff0c;Jenkins是支持参数化构建的。 以下是Jenkins官…

常用 各国语言简写

zh-CN 华 -中国 zh-TW 华 -台湾 zh-CHS 华 (单一化) zh-SG 华 -新加坡 zh-CHT 华 (传统的) zh-HK 华 - 香港的 SAR zh-MO 华 - 澳门的 SAR en 英国 en-US 英国 - 美国 en-AU 英国 -澳洲 en-BZ 英国 -伯利兹 en-CA 英…

VUE2拖拽组件:vue-draggable-resizable-gorkys

vue-draggable-resizable-gorkys组件基于vue-draggable-resizable进行二次开发, 用于可调整大小和可拖动元素的组件并支持冲突检测、元素吸附、元素对齐、辅助线 安装: npm install --save vue-draggable-resizable-gorkys 全局引用: import Vue from vue import vdr fro…

推荐Bulk Image Downloader插件下载网页中图片链接很好用

推荐&#xff1a;Bulk Image Downloader chome浏览器插件下载图片链接&#xff0c;很好用。 有个网页&#xff0c;上面放了数千的gif的电路图&#xff0c;手工下载会累瘫了不可。想找一个工具分析它的静态链接并下载&#xff0c;找了很多推荐的下载工具&#xff0c;都是不能分…

Ubuntu20.04更新GLIBC到2.35版本

目录 1 背景2 增加源2.1 标准源2.2 镜像源 3 更新 1 背景 Ubuntu20.04默认GLIBC库版本是2.31.今天碰到一个软件需要2.35版本的GLIBC。 升级GLIBC库有两种方式&#xff1a; 下载高版本库源码&#xff0c;编译后替换系统中低版本库。由于GLIBC库是Linux系统中最基础库&#xff…

方法引用详解

什么是方法引用&#xff1f;&#xff1a;针对于函数式接口中的抽象方法 为什么用方法引用&#xff1f;&#xff1a;避免代码的重复&#xff0c;简便书写&#xff0c;提高效率 在使用Lambda表达式的时候&#xff0c;我们实际上传递进去的代码就是一种解决方案&#xff1a;拿参数…