//如果打印了a的值就表示替换失败 std::cout<<a<<std::endl; return 0; } 2.execv 函数 函数原型: int execv(const char* path,char* const argv[]); 函数解释: 1.把这个和1号函数进行比较,唯一的区别就是后面不一样: execv传递的是一个 }; //int a=execv
execl() 和 execv() 提供了简化接口,execl() 使用可变参数,execv() 使用参数数组。 execlp() 和 execvp() 可以根据 PATH 环境变量搜索程序。 () execv() 是 execve() 的简化版本,不需要传递环境变量,只需要路径和参数数组。 在该例中,execv() 使用参数数组执行 ls。 execv("/bin/ls", argv); // 传递参数数组 perror("execv error"); return 0; } 6、execvp() execvp( ) 和 execv() 类似,但它会根据 PATH 环境变量查找可执行文件。
,char *const argv,···); int execle(const char *path,char *const argv,···· ,char *const envp[]); int execv NULL ) == -1 ) { perror( "execl error " ); exit(1); } } /** *创建子进程并调用函数execv *execv中希望接收一个以NULL结尾的字符串数组的指针 */ if( fork() == 0 ) { // in child printf("2------- -----execv------------\n"); if( execv( "/bin/ls",arg) < 0) { perror("execv error ");
二、exec族函数的介绍和实战: 1、还是老套路,首先我们用man 3 exec来查看有哪些exec族函数: NAME execl, execlp, execle, execv, execvp, The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated 说明与实战demo: a、我们首先来分析execl和execv : int execl(const char *path, const char *arg, ... /* (char *) NULL */); int execv(const char *path, char *const argv[]); 这两个函数是最基本的exec族函数,都可以用来执行一个程序,区别是传参的格式不同 execv函数。
运行结果: 2.4 execv() 函数 execv()是execve()的一个封装,允许你提供程序路径和参数数组。它不通过$PATH查找程序,而是需要提供完整的程序路径。 "-l", NULL}; // 命令行参数 printf("Before execv\n"); // 使用完整路径执行命令 execv("/bin/ls", args); printf("This will not be printed if execv is successful. \n"); return 0; } 在这个示例中,execv()会用完整路径/bin/ls来执行命令。如果execv()调用成功,后续的printf语句将不会执行。 execv 与execve类似,但不查找$PATH,需要提供完整路径。 execl 与execlp类似,但以参数列表的形式传递命令行参数。
std::string command_line(android::base::Join(arg_vector, ' ')); *error_msg = StringPrintf("Failed execv nullptr : Runtime::Current()->GetEnvSnapshot(); if (envp == nullptr) { execv(program, &args _exit(1); } else { if (pid == -1) { *error_msg = StringPrintf("Failed to execv(%s) because = pid) { *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
execl中,l:list,列表 path:需要执行的路劲,需要带路劲 后面的参数:在命令行中怎么执行 例如: execl("/usr/bin/ls","ls","-l","-a",NULL); execv execv(const char *path, char *const argv[]); v(vector) : 参数用数组 if(id==0) { sleep( ,"--color",NULL}; //child // execl("/usr/bin/ls","ls","-l","-a",NULL); execv --color",NULL}; //child // execl("/usr/bin/ls","ls","-l","-a",NULL); // execv "-a","--color",NULL}; //child // execl("/usr/bin/ls","ls","-l","-a",NULL); // execv
hooked) { HOOK(execv); hooked = true; } enable = true; } 说明在 TurboDex 中 , 禁用 dex2oat 是通过 Hook execv 博客章节分析的源码结论相同 ; 在 exec_utils.cc#ExecAndReturnCode 源码中 , 有如下代码片段 : if (envp == nullptr) { execv aospxref.com/android-8.0.0_r36/xref/art/runtime/exec_utils.cc#ExecAndReturnCode ; 有的 ART 虚拟机需要 Hook execv
,char* const envp[]); int execv(const char* path,char* const argv[]); int execvp(const char* file,char 函数名 参数格式 是否带路径 是否使用当前环境变量 execl 列表 不是 是 execlp 列表 是 是 execle 列表 不是 不是,需要自己组装环境变量 execv 数组 不是 是 execvp 函数 execv和execl函数没什么区别。 execv函数把execl的以列形式的传参,变成了以数组的形式的传参。 ("/bin/ls",argv); //如果execv执行成功,下行将不会被执行。
execv 在执行一个程序时,第一步仍然是要找到这个程序。与 execlv 相似,execv 需要我们提供程序的 路径 和 参数数组。 execv 的第一个参数是要执行的程序的完整路径或相对路径,后续参数是传递给程序的选项和参数,这些选项和参数通过一个数组来传递。数组的最后一个元素必须是 NULL,用来标识参数的结束。 unistd.h> int main() { // 创建一个参数数组 char *args[] = {"ls", "-l", "/home", NULL}; // 使用 execv 执行程序 /bin/ls execv("/bin/ls", args); // 如果 execv 执行失败,则打印错误信息 perror("execv failed" execv 不会在 PATH 环境变量中查找程序,因此必须提供程序的 绝对路径 或 相对路径。在这个例子中,路径是 /bin/ls,表示我们要执行 ls 命令。
\n"); return 0; } 可以看出,函数 execl 中的 命令+选项+NULL 是以 链式 的方式进行传递的 2.2、函数2 execv 替换函数 execv 是以顺序表 vector 的方式传递 参数2~N 的 #include <unistd.h> int execv(const char* path, char* const argv[]); 函数解读 返回值:替换失败返回 * const argv[] = { "ls", "-a", "-l", NULL }; //argv 表,实际为指针数组 execv ("子进程替换失败,异常终止 exit_code:%d\n", WEXITSTATUS(status)); } return 0; } 正常运行的情况 错误运行的情况,改变 path execv ("/usr/bin", argv); //故意提供错误路径 与 execl 函数不同,execv 是以表的形式进行参数传递的 2.3、函数3 execlp 可能有的人觉得写 path 路径很麻烦
build/lite') hb_dir = search(lite_dir, '__entry__.py') param_list = ["python3", "-c", EXECV_FRAGMENT param_list.append(hb_dir) os.environ['PATH'] = python_dir + ":" + os.getenv('PATH') os.execv 在解释动态执行python代码片段EXECV_FRAGMENT时,提到的sys.argv.pop()就是刚刚添加的这个目录。接下来,⑹处的代码设置环境变量,然后调用函数os.execv来执行。 lite') hb_dir = search(lite_dir, '__entry__.py')⑶ param_list = ["python3", "-c", EXECV_FRAGMENT param_list.append(hb_dir)⑹ os.environ['PATH'] = python_dir + ":" + os.getenv('PATH') os.execv
+ = cmd; *parg++ = "-al"; *parg++ = "/proc/self/fd"; *parg = NULL; execv n", status); } return 0; } 需要先安装libseccomp-dev(apt-get install libseccomp-dev),编译的时候: gcc execv.c -g -o execv -lseccomp 运行可以发现,子进程并不是正常退出的。
\n"); return 0; } 3.2、execv/execvp execv的用法与execl的用法大致相同,只不过将execl后面的可变参数列表换成一个指针数组。 execvp也只是将execv前面的路径换成程序名而已。不过这里要强调的是:不要忘了路径最前面的那一个斜杠,还有数组的结束标志是NULL,一定要在数组的最后加上NULL。 == 0) { char* argv[] = {"ls", "-l", "-a", NULL}; //execvp("ls", argv); execv
,char *const envp[]); int execv(const char *path, char *const argv[]); int execvp(const char *file, char 2.3 execv 使用的时候包含头文件unistd.h。 为什么取名叫execv?v对应vector。因为execv在传递第二个参数的时候,与execl不同,它传递的是一个参数数组。—参数以数组形式传入。 还有一点不同,参数类型execl要求的是const char*,直接传入字符串常量就行,而execv要求的是char*,在数组里面还要给字符串常量强转成char*。 2.4 execlp和execvp execlp相比于execl多了个p,execvp相对于execv也是同样,这个p就是PATH环境变量,这两个函数的第一个参数是file,也就是要我们传递所要执行文件的名字
4 认识所有函数并使用 所有的函数一共有execl execlp execle execv execvp execvpe,不难发现,拿命令行参数进行举例的话,选项一共有l p e v。 第二个函数: execv,这里面的v代表的是vector,C++中的顺序表,所以我们看execv的参数是[],也就是我们应该这样干: int main() { char* const argv[ *)"ls", (char*)"-l", (char*)"-a", (char*)"--color", NULL }; execv "ls", (char*)"-l", (char*)"-a", (char*)"--color", NULL }; //execv
/my_program", "arg1", "arg2", NULL}; if (execv(". } execv 函数会执行当前目录下的 my_program 程序,并传递 "arg1" 和 "arg2" 作为命令行参数。 // 错误示例:缺少NULL结尾 char *args[] = {"ls", "-l"}; execv("/bin/ls", args); // 可能崩溃! 可能原因: 路径问题:使用 execl()、execv()、execle()、execve() 时,指定的程序路径可能错误或文件不存在。 环境变量继承问题:使用 execl()、execlp()、execv()、execvp() 时,继承的环境变量不符合新程序要求。
,char *const argv,···); int execle(const char *path,char *const argv,···· ,char *const envp[]); int execv NULL ) == -1 ) { perror( "execl error " ); exit(1); } } /** *创建子进程并调用函数execv *execv中希望接收一个以NULL结尾的字符串数组的指针 */ if( fork() == 0 ) { // in child printf("2------- -----execv------------\n"); if( execv( "/bin/ls",arg) < 0) { perror("execv error ");
2.2 execv函数 第二个函数我们来讲execv,这个函数相比于上面的execl看起来也就是参数有些不同罢了,其实也就是参数不同。 那么execv的第二个参数这个数组是怎么个事呢? 其实execv这个函数与execl就只是传参方式不同罢了,execl需要直接传参,而execv则是将要传的参数写入一个数组中,在将数组传进去,就这么点区别,所以execv的v也就是我们常见的vector 这里我们要用到main函数的参数argv,也就是我们之前讲过的命令行参数,我们让arg指针指向argv的第二个数据,因为第一个数据是我们要执行的文件,后面才是要怎么执行,并将argv的第一个数据传给execv /myexec即可,但其实底层在传参时是按照上面的参数进行传参的,无非就是execv中的参数有两个/usr/bin/ls而已,不影响,我们之前第二个参数不写路径是因为第一个参数已经写过路径了,系统已经能找到要执行的文件了 2.3 execlp函数和execvp函数 因为上面的execl和execv非常相似,这里的execlp和execvp同样也是如此,所以将这两个函数放在一块讲,我们先来看看这两个函数: 依旧是传参形式不同
) { printf("[%d]: %s\n", i, env[i]); } return 0; } 这是exec*函数程序替换,我们在下文会讲 2.2 execv 类型函数 execv其实就是在execl的基础上多了一个指针数组,情况大差不差我们就不具体介绍了! 具体关系如下图: execv 和 execvp: int main() { char *const argv[] = { "ls", "-a", "-l", NULL } ; printf("pid: %d, exec command begin\n", getpid()); sleep(2); execv("/usr/bin/ls", argv)