【Linux】进程替换、命令行参数及环境变量(超详解)

news/2024/12/22 1:20:26/

目录

进程替换

替换函数的含义

命令行参数

环境变量

PATH


进程替换

我们先看代码:

  1 #include<stdio.h>2 #include<unistd.h>3 int main()4 {5     printf("process...begin!\n");6 7     execl("/usr/bin/ls","ls","-a","-l",NULL);8 9     printf("process...end!\n");10     return 0;11 }

运行结果:

 

通过运行结果,我们会发现:

 printf("process...end!\n");并没有被执行;

这是为什么?

我们先来看一下exec函数:

还有一个:int execve(const char *path, char *const argv[], char *const envp[]);

exec函数其实就是替换函数,图像表示:

        以上述代码为例:execl("/usr/bin/ls","ls","-a","-l",NULL);就是将磁盘中的有一段程序的代码和数据替换掉父进程在内存中的代码和数据;exec*执行完毕后,后续的代码不见了,是因为被exec*替换了,所以不会执行exec*后面的代码,简单来说:被替换后后面代码已经找不到了,自然不会被执行;

        这个替换,本质就是这个程序被加载到内存了(exec*函数类似于一种Linux上的加载函数);

那我们非要让后面的代码可以执行,要怎么做呢?

        很简单,父进程中exec*函数后的代码无法执行是因为exec*函数的替换,把后续代码给替代了,找不到后续代码;那我们让后续代码可以找到不就可以了?怎么让它可以找到-------->fork创建子进程,在子进程中执行exec*函数,这就是用的我们之前提到的写实拷贝(让子进程自己去替换,父进程的代码和数据不受影响);

  1 #include<stdio.h>2 #include<unistd.h>3 #include<stdlib.h>4 int main()5 {6     printf("process...begin!\n");7 8     pid_t id =fork();9     if(id==0)10     {11         execl("/usr/bin/ls","ls","-a","-l",NULL);12         exit(1);13     }14     //父进程15     sleep(5);16     printf("process...end!\n");17     return 0;18 }

这样父进程后续代码就可以被执行了;

原理是什么呢?

一开始,子进程完全的父进程的拷贝(页表指向是红色箭头),后面由于exec*函数替换,因为替换的不仅仅是数据,连代码也替换了,这时OS就是进行写时拷贝,把代码和数据都复制了一份(绿色和蓝色箭头的指向);父进程代码和数据仍然存在;

替换函数的含义

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

这个l指的是list 列表,path就是要执行程序的路径,arg:在命令行中怎么执行,这个就怎么写:

例如:ls -a ---->"ls","-a",即可;最后一个参数必须为NULL;

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

这个v指的是vector,path是路径,argv:就是把命令放到argv里面;

例如:

(3)int execlp(const char *file, const char *arg, ...);

用户可以不传要执行文件的路径,但是要传文件名,直接告诉exec*函数,我要执行谁;

这里的p:查找这个程序,系统会在环境变量PATH进行查找;

例如:

(4)int execle(const char *path, const char *arg, ...,char *const envp[]);

这里的e:environment:环境变量; envp[]:整体替换所有的环境变量;

例如:

当然,除了可以替换系统命令,也可以替换我们自己写的程序:

先写一个程序:test.c,然后执行:

使用: 

即可:

运行结果:

命令行参数

我们发现在main函数中可带参数,也可以不带参数;

带参数:

这个参数有什么用呢?

我们看下面的代码,将argv打印出来:

运行结果:

根据运行结果我们可以理解:命令行参数本质是交给我们程序的不同选型,用来定制不同的程序功能,命令中会携带很多选项;

例如:ls -a;

           ls -l;等

环境变量

        在Linux中,存在一些全局的设置,表明,告诉命令行解释器应该取哪些路径下去寻找可执行程序;

PATH

PATH:环境变量;

$PATH:打印环境变量内存;

系统中很多的配置,在登录Linux系统的时候,已经加载到bash进程中(内存);

我们发现ls命令:并不需要./,但是我们自己写的程序,比如myprocess,运行时却要./myprocess才可以运行,这是为什么?

我们只需要将我们的程序配置到环境变量中即可;

那怎么配置呢?

/PATH=$PATH:路径;

例如:

        PATH=$PATH:home/sxh/111/lesson06;

因为我们配置的这个PATH是在内存中,重启后,PATH就会复原;

当然,除了PATH,还有其他的环境变量,比如:HOME/SHELL/HISISIZE/PWD等;

env:查看所有环境变量

echo $xxx:查看某一个环境变量

export name=value:设置环境变量

unset name:取消环境变量

怎么打印环境变量?

运行结果:

注意:环境变量默认是可以被子进程拿到的;


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

相关文章

【QT】亲测有效:“生成的目标文件包含了过多的段,超出了编译器或链接器允许的最大数量”错误的解决方案

在使用dlib开发人脸对齐功能时&#xff0c;出现了”生成的目标文件包含了过多的段&#xff0c;超出了编译器或链接器允许的最大数量的错误“。 主要功能代码如下&#xff1a; #include <QApplication> #include <QImage> #include <QDebug>#include <dlib…

rust的nutyp验证和validator验证数据的方法

使用nutype验证 Cargo.toml nutype { version "0.5.0", features ["serde","regex"] } regex "1" thiserror "1"modules.rs #[nutype(sanitize(trim, lowercase),validate(not_empty, len_char_min 3, len_char_max …

《OpenCV》—— 指纹验证

用两张指纹图片中的其中一张对其验证 完整代码 import cv2def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)def verification(src, model):sift cv2.SIFT_create()kp1, des1 sift.detectAndCompute(src, None)kp2, des2 sift.detectAndCompute(model, None)fl…

国庆刷题(day2)

C语言刷题&#xff1a; C刷题&#xff1a;

http请求过程 part-2

http请求过程 http应用层 实体 实体分为实体首部和实体主体&#xff0c;实体首部是用来描述主体的 实体部分是可选的&#xff0c;它被用来运送请求或者响应的数据 传输层-TCP HTTP连接是建立在TCP连接的基础上 以流形式通过一条已经打开的TCP连接&#xff0c;按顺序进行…

移动端的每日任务,golang后端数据库应该怎么设计

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

决策树的损失函数公式详细说明和例子说明

公式的详细说明 L α ( T ) ∑ t 1 ∣ T ∣ N t H t ( T ) α ∣ T ∣ L_{\alpha}(T) \sum_{t1}^{|T|} N_t H_t(T) \alpha |T| Lα​(T)t1∑∣T∣​Nt​Ht​(T)α∣T∣ 这是决策树的损失函数&#xff0c;它由两部分组成&#xff1a; ∑ t 1 ∣ T ∣ N t H t ( T ) \sum_…

rabbitMq------客户端模块

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言消费者模块信道管理模块管理的字段提供的接口 信道内存管理连接管理类 前言 在RabbitMQ中&#xff0c;提供服务的是信道&#xff0c;因此在客⼾端的实现中&…