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

【Linux进程控制】进程程序替换

目录

进程程序替换

替换函数

看现象

替换原理

多进程替换

exec*函数使用(部分),并且认识函数参数的含义

1.execl

2.execv

3.execvp

4.execvpe

execlp 和execlpe

替换函数总结


进程程序替换

替换函数

有六种以exec开头的函数,统称exec函数:

EXEC(3)                  Linux Programmer's Manual                 EXEC(3)NAMEexecl, execlp, execle, execv, execvp, execvpe - execute a fileSYNOPSIS#include <unistd.h>extern char **environ;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[]);int execvpe(const char *file, char *const argv[],char *const envp[]);Feature Test Macro Requirements for glibc (see feature_test_macros(7)):execvpe(): _GNU_SOURCE

看现象

测试代码:

#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;
}

结果:

[wuxu@Nanyi lesson17]$ ./test
testexec ... begin!
total 56
drwxrwxr-x  2 wuxu wuxu 4096 Aug 25 15:18 .
drwx------ 11 wuxu wuxu 4096 Aug 24 19:49 ..
-rw-rw-r--  1 wuxu wuxu    1 Aug 25 15:14 myprocess
-rw-rw-r--  1 wuxu wuxu  182 Aug 25 15:18 myprocess.c
-rw-rw-r--  1 wuxu wuxu 1809 Aug 24 21:34 task.c
-rwxrwxr-x  1 wuxu wuxu 8416 Aug 25 15:18 test
-rw-rw-r--  1 wuxu wuxu  366 Aug 24 20:02 test1.c
-rw-rw-r--  1 wuxu wuxu  934 Aug 24 20:16 test2.c
-rw-rw-r--  1 wuxu wuxu  501 Aug 24 20:33 wait1.c
-rw-rw-r--  1 wuxu wuxu  583 Aug 24 20:56 wait2.c
-rw-rw-r--  1 wuxu wuxu  469 Aug 24 20:58 wait3.c
-rw-rw-r--  1 wuxu wuxu 1407 Aug 24 21:24 wait4.c

通过观察我们发现:

◉ 第一个printf执行了

◉ ls命令被执行了

◉ 最后一个printf没有被执行

说明程序在execlls替换了,替换也是完完全全的,并不会执行后面的代码

替换原理

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

站在被替换进程的角度:本质就是这个程序被加载到内存了;如何加载?exec*类似于一种Linux上的加载函数

多进程替换

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);}// fahterint 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;
}

 

[wuxu@Nanyi lesson17]$ gcc -o test myprocess.c -std=c99
[wuxu@Nanyi lesson17]$ ./test
testexec ... begin!
child pid: 8233
total 56
drwxrwxr-x  2 wuxu wuxu 4096 Aug 25 16:29 .
drwx------ 11 wuxu wuxu 4096 Aug 24 19:49 ..
-rw-rw-r--  1 wuxu wuxu    1 Aug 25 15:14 myprocess
-rw-rw-r--  1 wuxu wuxu  540 Aug 25 16:29 myprocess.c
-rw-rw-r--  1 wuxu wuxu 1809 Aug 24 21:34 task.c
-rwxrwxr-x  1 wuxu wuxu 8720 Aug 25 16:29 test
-rw-rw-r--  1 wuxu wuxu  366 Aug 24 20:02 test1.c
-rw-rw-r--  1 wuxu wuxu  934 Aug 24 20:16 test2.c
-rw-rw-r--  1 wuxu wuxu  501 Aug 24 20:33 wait1.c
-rw-rw-r--  1 wuxu wuxu  583 Aug 24 20:56 wait2.c
-rw-rw-r--  1 wuxu wuxu  469 Aug 24 20:58 wait3.c
-rw-rw-r--  1 wuxu wuxu 1407 Aug 24 21:24 wait4.c
father wait success, child exit code: 0
testexec ... end!

原理如图:即便是父子,也要保证独立性

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);}// fahterint 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*)"-a",    (char*)"--color",NULL};execvp("ls",argv);exit(1);}// fahterint 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*)"--color",NULL};extern char** environ;execvpe("ls",argv,environ);exit(1);}// fahterint 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

方法与上面相同,就不再一一介绍了

替换函数总结

函数名参数格式PATH中可执行程序是否需要带绝对路径是否使用当前环境变量
execl列表
execlp列表不是
execle列表不是,需自己组装环境变量
execv数组
execvp数组不是
execvpe数组不是不是,需自己组装环境变量
execve数组不是,需自己组装环境变量

上面各个接口统称为加载器,它们为即将替换进来的可执行程序加载入参数列表、环境变量等信息。下面我们使用execvpe接口给自定义可执行程序传入命令行参数及环境变量,该可执行程序将会把命令行参数及环境变量打印至显示器

myprogma.cc:

#include <iostream>
#include <unistd.h>
using namespace std;int main(int argc, char* argv[], char* env[]){int i = 0;for(; argv[i];i++){printf("argv[%d] : %s\n",i , argv[i]);}printf("-------------------------\n");for(i = 0; env[i]; i++){printf("env[%d]: %s\n",i , argv[i]);}printf("-------------------------\n");cout << "hello C++, I am a C++ program! : " << getpid() << endl;cout << "hello C++, I am a C++ program! : " << getpid() << endl;cout << "hello C++, I am a C++ program! : " << getpid() << endl;cout << "hello C++, I am a C++ program! : " << getpid() << endl;return 0;
}

 testfin.c:

#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("HHHH=111111111111111111");// 我的父进程本身就有一批环境变量!!!, 从bash来char *const argv[] = {(char*)"mypragma",(char*)"-a",(char*)"-b",NULL};extern char** environ;printf("child pid: %d \n",getpid());sleep(2);// execvpe("./myprogma",argv,environ);execl("/usr/bin/python3","python3","test.py",NULL);exit(1);}//fatherint 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;
}

test.py

print("hello python")
print("hello python")
print("hello python")
print("hello python")
print("hello python")

test.sh:

cnt=0
while [ $cnt -le 10 ]
doecho "hello shell, cnt: ${cnt}"let cnt++done

编译运行:

其他几个例子也就不一一测试了

下图exec函数族一个完整的例子:

 

相关文章:

【Linux进程控制】进程程序替换

目录 进程程序替换 替换函数 看现象 替换原理 多进程替换 exec*函数使用&#xff08;部分&#xff09;&#xff0c;并且认识函数参数的含义 1.execl 2.execv 3.execvp 4.execvpe execlp 和execlpe 替换函数总结 进程程序替换 替换函数 有六种以exec开头的函数&am…...

02 ETH

以太坊与比特币有什么不同&#xff1f; 以太坊立足比特币创新之上&#xff0c;于 2015 年启动&#xff0c;两者之间有一些显著不同。 比特币就仅仅是比特币&#xff1b;以太坊包括以太币&#xff0c;以太币才是和比特币对等的存在。以太坊是可编程的&#xff0c;所以你可以在…...

web渗透—RCE

一&#xff1a;代码执行 相关函数 1、eval()函数 assert()函数 (1)原理&#xff1a;将用户提交或者传递的字符串当作php代码执行 (2)passby:单引号绕过&#xff1a;闭合注释&#xff1b;开启GPC的话就无法绕过&#xff08;GPC就是将单引号转换为"反斜杠单引号"&a…...

HomeAssistant显示节假日

先看效果 步骤&#xff1a; 新建卡片时选择“Markdown 卡片”代码在文章最下方&#xff0c;当然你也可以自己修改 点击保存/完成 ### {% if now().hour > 6 and now().hour < 9 -%} 早上好&#xff0c; {%- elif now().hour > 9 and now().hour < 12 -%} 上午好…...

AI问答-HTTP:理解 Content-Disposition

本文背景 在下载arraybuffer文件时&#xff0c;想要获取文件名&#xff0c;这时引入本文内容Content-Disposition&#xff0c;我们在Content-Disposition获取到文件名就可以在下载后的文件以该文件名命名了。 一、简介 Content-Disposition是HTTP协议中的一个响应头字段&…...

kubernetes架构

kubernetes cluster由master和node组成&#xff0c;节点上运行着若干kubernetes服务Master节点&#xff1a; master是kubernetes cluster的大脑&#xff0c;运行着的Daemon服务包括kube-apiserver&#xff0c;kube-scheduler,kube-controller-manager&#xff0c;etcd和Pod网络…...

【隐私计算篇】中国剩余定理解释以及Paillier解密加速应用

1. 背景介绍 本篇主要关注中国剩余定理的原理以及在paillier同态加密系统中的应用。在很多工作中&#xff0c;都可以看到中国剩余定理的影子&#xff0c;特别是同态加密提升计算效率的优化工作中&#xff0c;将paillier与中国剩余定理进行结合&#xff0c;能够实现在加密状态下…...

保护您的隐私:隐藏 IP 地址的重要性

在当今的数字时代&#xff0c;我们的在线隐私和安全变得比以往任何时候都更加重要。浏览互联网时保护自己的一种方法是隐藏您的 IP 地址。 但是为什么要隐藏您的 IP 地址以及如何有效地做到这一点&#xff1f; 隐藏您的 IP 地址有助于保护您的在线匿名性。您的 IP 地址就像您的…...

nodejs 007:错误npm error Error: EPERM: operation not permitted, symlink

完整错误信息 npm error Error: EPERM: operation not permitted, symlink npm warn cleanup Failed to remove some directories [ npm warn cleanup [ npm warn cleanup C:\\Users\\kingchuxing\\Documents\\IPFS\\orbit-db-set-master\\node_modules\\ipfs-cli, npm…...

Rsync未授权访问漏洞复现及彻底修复

一、什么是 Rsync&#xff1f; Rsync 是一种广泛使用的文件传输工具&#xff0c;它允许系统管理员和用户通过局域网&#xff08;LAN&#xff09;或广域网&#xff08;WAN&#xff09;在计算机之间同步文件和目录。Rsync 支持通过本地或远程 shell 访问&#xff0c;也可以作为守…...

影刀RPA实战:网页爬虫之携程酒店数据

1.实战目标 大家对于携程并不陌生&#xff0c;我们出行定机票&#xff0c;住酒店&#xff0c;去旅游胜地游玩&#xff0c;都离不开这样一个综合性的网站为我们提供信息&#xff0c;同时&#xff0c;如果你也是做旅游的公司&#xff0c;那携程就是一个业界竞争对手&#xff0c;…...

【UCB CS61C】Lecture 5 - Floating Point

目录 引入浮点数&#xff08;Floating Point&#xff09;定点表示法&#xff08;Fixed-Point Model&#xff09;科学记数法&#xff08;Scientific Notation&#xff09;记数法间的转换 IEEE 754 二进制浮点数算术标准实现目标单精度浮点编码阶码字段&#xff08;The Exponent …...

【Binlog实战】:基于Spring监听Binlog日志

【Binlog实战】&#xff1a;基于Spring监听Binlog日志 binlog的三种模式 MySQL 的二进制日志&#xff08;binlog&#xff09;有三种不同的格式&#xff0c;通常被称为 binlog 模式。这三种模式分别是 Statement 模式、Row 模式和Mixed 模式。 Statement 模式&#xff1a; 在 …...

鸿蒙OpenHarmony【轻量系统芯片移植】轻量系统STM32F407芯片移植案例

轻量系统STM32F407芯片移植案例 介绍基于STM32F407IGT6芯片在拓维信息[Niobe407]开发板上移植OpenHarmony LiteOS-M轻量系统&#xff0c;提供交通、工业领域开发板解决方案。移植架构采用Board与SoC分离方案&#xff0c;使用arm gcc工具链Newlib C库&#xff0c;实现了lwip、l…...

基于SpringBoot+定时任务实现地图上绘制车辆实时运动轨迹图

目录 1. 项目结构 2. Maven依赖配置 (pom.xml) 3. 实现后端服务 4. 配置文件 (application.properties) 5. 启动项目 6. 访问页面 实现基于北斗卫星的车辆定位和轨迹图的Maven工程&#xff08;使用模拟数据&#xff09;&#xff0c;我们将使用以下技术&#xff1a; Spri…...

Rasa对话模型——做一个语言助手

1、Rasa模型 1.1 模型介绍 Rasa是一个用于构建对话 AI 的开源框架&#xff0c;主要用于开发聊天机器人和语音助手。Rasa 提供了自然语言理解&#xff08;NLU&#xff09;和对话管理&#xff08;DM&#xff09;功能&#xff0c;使开发者能够创建智能、交互式的对话系统。 1.2…...

golang学习笔记19——golang做服务发现与注册的深度剖析

推荐学习文档 golang应用级os框架&#xff0c;欢迎stargolang应用级os框架使用案例&#xff0c;欢迎star案例&#xff1a;基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识&#xff0c;这里有免费的golang学习笔…...

ROS和ROS2借助智能大模型的学习和研究方法

机器人相关知识的本身和价值-CSDN博客 知识本身在智能时代毫无价值&#xff0c;需要基于知识应用和创新才有价值。 学历报废并非来自扩招&#xff0c;而是智能模型的快速发展。-CSDN blink-领先的开发者技术社区 2024年中秋&#xff0c;智能模型实力已经如此&#xff0c;但还…...

弹性负载均衡ELB 详解和设置方法

一、弹性负载均衡ELB 详解 1. 定义与概念 弹性负载均衡&#xff08;Elastic Load Balancing&#xff0c;简称ELB&#xff09;是一种将访问流量自动分发到多台云服务器的流量分发控制服务。它通过在多个后端服务器之间均衡分配请求&#xff0c;提高应用程序的可用性、可扩展性…...

Python3网络爬虫开发实战(15)Scrapy 框架的使用(第一版)

文章目录 一、Scrapy 框架介绍1.1 数据流1.2 项目结构1.3 Scrapy 入门 二、Selector 解析器2.1 XPath 和 CSS 选择器2.2 信息提取2.3 正则提取 三、Spider 的使用3.1 Spider 运行流程3.2 Spider 类分析3.3 Request3.4 Response 四、Download Middleware 的使用4.1 process_requ…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)

UniApp 集成腾讯云 IM 富媒体消息全攻略&#xff08;地理位置/文件&#xff09; 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型&#xff0c;核心实现方式&#xff1a; 标准消息类型&#xff1a;直接使用 SDK 内置类型&#xff08;文件、图片等&#xff09;自…...

pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决

问题&#xff1a; pgsql数据库通过备份数据库文件进行还原时&#xff0c;如果表中有自增序列&#xff0c;还原后可能会出现重复的序列&#xff0c;此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”&#xff0c;…...