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

程序替换接口

程序替换

  • 程序替换
    • main 函数回顾说明
    • 程序替换
      • execve 指定运行参数argv
      • execvp 不需要指定环境变量
      • execv
      • execl 、execlp 、execle
    • 程序替换的作用
  • 小点点

程序替换

main 函数回顾说明

main(int argc,char* argv[],char* env[])
argc:程序运行参数的个数
argv:程序运行参数,字符指针数组,最后一个参数之后,以NULL结尾
env:程序的环境变量,字符指针数组,最后一个参数之后,以NULL结尾
在这里插入图片描述

程序替换

execve 指定运行参数argv

int execve(char* path,char* argv[],char* env[]);
功能: 将 path 这个路径名所指定的程序加载到内存中,然后让当前进程调度管理这个程序的运行
argv:用于设定这个程序的运行参数
env:用于设定这个程序的环境遍历
返回值:替换成功运行新程序 没有返回值;失败返回-1

使用示例:

// execve.c 程序

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

int main()
{
  printf("这是我程序运行的起始位置~\n");

  char* argv[]={"-a","-d","-c","xzz",NULL};   //argv 字符函数必须以 NULL 结尾
  char* env[]={"MYVAL=999","CLASS=98",NULL};
  
//进行程序替换,argc 程序替换运行当前程序
  execve("./argc",argv,env);
  //execve("/bin/ls",argv,env);    //指定系统调用接口路径,指定运行参数和环境变量

   return 0;
}

其中所调用的 argc 程序:

//argc.c 程序

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

int main(int argc,char* argv[],char* env[])
{
  int i=0;
  for(;argv[i]!=NULL;++i)   //将运行参数打印
    printf("argv[%d]=[%s]\n",i,argv[i]);

  printf("~~~~~~~~~~~~~~~~~~\n");

  i=0;
  for(;env[i]!=NULL;++i)   //打印环境变量
    printf("env[%d]=[%s]\n",i,env[i]);

  return 0;
}

运行结果:
在这里插入图片描述

execvp 不需要指定环境变量

int execvp(char* file,char* argc[],cahr* env);
第一个参数不用指定路径,默认会在 PATH环境变量指定的路径下找
环境变量默认使用当前已有的,不用手动设置环境变量

使用示例:

int main()
{
  printf("这是我程序运行的起始位置~\n");

  //char* argv[]={"-a","-d","-c","xzz",NULL};   //argv 字符函数必须以 NULL 结尾
  //char* env[]={"MYVAL=999","CLASS=98",NULL};
 // execve("./argc",argv,env);

  
  char *argv[]={"ls","-l",NULL};
  char* env[]={NULL};
  
  //使用运行参数 argv 中 ls -l 替换当前程序
  execvp("ls",argv);   
  //env 默认采用已有的环境变量,且不需要指定路径

//execvp("./argc",argv);
  
 // 等价于 execve("ls",argc,env-main中第三个参数)

  printf("这是我程序运行的终止~~~\n");


  return 0;
}

在这里插入图片描述

execv

int execv(char* path,char* argv[]);
不用设置环境变量,但是需要路径

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

int main()
{
  printf("这是我程序运行的起始位置~\n");
  
  char *argv[]={"ls","-l",NULL};

  execv("ls",argv);   //不指定路径时会发生错误
  perror("execv error\n");

  printf("这是我程序运行的终止~~~\n");
  return 0;
}

当没有指定 ls 的位置时,会发生替换失败:

在这里插入图片描述

当指定路径之后:

execv("/bin/ls",argv);

在这里插入图片描述

execv(“bin/ls”,argv); 需要指定路径
execvp(“ls”,argv); 不需要指定路径
execve(“bin/ls”,argv,env); 手动设置环境变量,并且需要指定路径

execl 、execlp 、execle

上述三种替换每次都需要定义一个参数字符指针数组,比较麻烦,因此常会这三种替换函数:

int execl(char* path,…/char arg*/);
int execlp(char* file,…);
int execle(char* path,…,char* env[]);

使用示例:

execlp("ls","ls","-l",NULL)        //可以不指定环境变量
execle("bin/ls","ls","-l",NULL,env)      //需要指定环境变量以及系统调用接口的路径

程序替换的作用

shell 是一个命令行解释器,捕捉用户的输入信息,了解用户想要干什么,然后执行对应的shell指令--------系统内核与用户之间沟通的桥梁

(1)父进程捕捉用户输入 [ ls -l -a ];
(2)解析输入,得到命令名称,各个参数 [ls] [-l] [-a];
(3)创建子进程;
(4)对子进程进行程序替换,将子进程要进行调度的程序换成要执行的 shell 指令程序;
(5)父进程等待子进程退出(等待指令执行完毕----避免僵尸进程),然后捕捉用户的下一个输入。

小点点

wc -l :统计个数(行数统计)
du :查看磁盘空间
pstree :查看目录的树形结构


Q1:不算main函数进程,一一共创建了多少个进程?

在这里插入图片描述

Q2:请问打印了多少个 * ?

int main()
{
	for(int i=0;i<2;++i){
		fork();
		printf("*\n");
	}
	return 0;
}

答案:6个

存在 \n 说明会刷新缓冲区,因此创建子进程时不会复制父进程内容(*)

在这里插入图片描述

Q3:请问打印了多少个 * ?

int main()
{
	for(int i=0;i<2;++i){
		fork();
		printf("*");
	}
	return 0;
}

答案:8个

不存在 \n 说明不会刷新缓冲区,因此 * 不会打印,暂时存储在缓冲区里,因此创建子进程会同时复制父进程缓冲区中内容(*)

在这里插入图片描述

相关文章:

  • 让GitHub低头认错的这份阿里内部绝密Java面试八股文手册有多强?
  • Linux——Linux驱动之玩转SPI(下)iMX6ULL驱动SPI接口的6轴MEMS传感器芯片实现数据采集开发实战
  • 【牛客刷题--SQL篇】多表查询组合查询SQL25 查找山东大学或者性别为男生的信息
  • Linux下驱动开发_块设备驱动开发(内存模拟存储)
  • vue -- 组件插槽 默认插槽 具名插槽 作用域插槽
  • [附源码]Java计算机毕业设计SSM高校教材管理系统
  • asp.net园林绿化服务交易网站
  • 网络精通-VRRP+MSTP
  • 无需专业设备和技能修复AOC显示器
  • Google Earth Engine APP——在线计算23类植被指数app代码
  • R语言---Ubuntu中R语言更新至R4.2.1和R包devtools下载
  • 笔试强训48天——day9
  • 什么是盒子模型中的边框
  • 2022海德堡桂冠论坛(HLF)见闻录
  • 动态规划-状态压缩、树形DP问题总结
  • CSS居中完全指南——构建CSS居中决策树
  • es的写入过程
  • Java深入 - 深入理解Java集合
  • java中具有继承关系的类及其对象初始化顺序
  • Theano - 导数
  • vue2.0项目引入element-ui
  • Xmanager 远程桌面 CentOS 7
  • Yii源码解读-服务定位器(Service Locator)
  • 翻译--Thinking in React
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 微信小程序实战练习(仿五洲到家微信版)
  • 微信支付JSAPI,实测!终极方案
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • C# - 为值类型重定义相等性
  • elasticsearch-head插件安装
  • 积累各种好的链接
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​secrets --- 生成管理密码的安全随机数​
  • ​力扣解法汇总946-验证栈序列
  • # Swust 12th acm 邀请赛# [ K ] 三角形判定 [题解]
  • # 数据结构
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • (2020)Java后端开发----(面试题和笔试题)
  • (多级缓存)多级缓存
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (四) Graphivz 颜色选择
  • (五)Python 垃圾回收机制
  • (学习日记)2024.01.19
  • (转)负载均衡,回话保持,cookie
  • .Family_物联网
  • .NET Core 和 .NET Framework 中的 MEF2
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • .NET多线程执行函数
  • .Net下的签名与混淆
  • .NET中使用Protobuffer 实现序列化和反序列化
  • /etc/sudoer文件配置简析
  • @31省区市高考时间表来了,祝考试成功