专门做产品排名的网站,凡科建设网站安全吗,凡客诚品官网商城首页,如何开网站卖东西目录
进程程序替换
替换函数
看现象
替换原理
多进程替换
exec*函数使用#xff08;部分#xff09;#xff0c;并且认识函数参数的含义
1.execl
2.execv
3.execvp
4.execvpe
execlp 和execlpe
替换函数总结 进程程序替换
替换函数
有六种以exec开头的函数部分并且认识函数参数的含义
1.execl
2.execv
3.execvp
4.execvpe
execlp 和execlpe
替换函数总结 进程程序替换
替换函数
有六种以exec开头的函数统称exec函数
EXEC(3) Linux Programmers Manual EXEC(3)NAMEexecl, execlp, execle, execv, execvp, execvpe - execute a fileSYNOPSIS#include unistd.hextern 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.hint main(){printf(testexec ... begin!\n);execl(/usr/bin/ls,ls,-a,-l,NULL);printf(testexec ... end!\n);return 0;
}
结果
[wuxuNanyi 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没有被执行
说明程序在execl被ls替换了替换也是完完全全的并不会执行后面的代码
替换原理
用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.hint 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;
} [wuxuNanyi lesson17]$ gcc -o test myprocess.c -stdc99
[wuxuNanyi 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 可以理解为listpath传入绝对路径arg可变参数依次传入命令以及你想执行的指令最后一个必须为NULL
2.execv
函数原型
int execv(const char *path, char *const argv[]);
这里的 v 可以理解为vectorargv是一个指针数组我们直接来使用
#include stdio.h
#include unistd.h
#include stdlib.h
#include sys/types.h
#include sys/wait.hint 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.hint 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.hint 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.hint main(){printf(testexec ... begin! \n);pid_t id fork();if(id 0){putenv(HHHH111111111111111111);// 我的父进程本身就有一批环境变量, 从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:
cnt0
while [ $cnt -le 10 ]
doecho hello shell, cnt: ${cnt}let cntdone
编译运行 其他几个例子也就不一一测试了
下图exec函数族一个完整的例子