Linux的进程替换
前5个方法是库函数,最后一个方法execve是系统调用,上面5个方法都是通过最后一个方法系统调用实现的。
3394是bash的pid,ps的父进程的pid是3394,也就是bash
bash命令解释器把自己fork一下,产生一个子进程,还叫bash,然后把这个子进程执行exec替换成我们想要执行的命令。
替换为ps,ps就执行出来了。
ps和bash两个命令没有关联,完全不同。
命令解释器bash就是不断的复制自己,再把自身替换成想要执行的程序。
第一个参数是:用谁来替换,然后是第一个参数,第二个参数…参数个数不固定,怎么确定参数的个数?-----要求最后一个参数是空指针。
我们接下来运行一个程序,然后把当前程序替换为ps,ps在/bin/ps中
Linux的进程替换的图解
下面是代码实现
下面是成功的结果
下面是失败的结果
execl执行失败返回perror(“execl error”)
execl 执行成功不返回,直接从新程序的主函数开始执行,只有失败才返回错误码
以下是其他的实现方式
下面是代码实现
execve是对上面方法的总和
fork 和 exec 联合使用创建一个全新的进程
由上图我们可知,ps-f的父进程的pid是5598,对应的是bash
这是怎么由来的呢?
看下面图解
bash不断把自己进行复制 然后替换成我们想要的进程
当前主程序复制产生一个子进程,子进程用新程序“b”替换自身。
当前主程序如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
int main(int argc, char* argv[],char* envp[])
{
printf("main pid=%d\n",getpid());
pid_t pid = fork();
assert( pid != -1 );
if ( pid == 0 )
{
char * myargv[] = {"b","hello","abc","123",(char*)0};
//char * myenvp[] = {"MYSTR=hello","VAL=100",(char*)0};
execve("./b",myargv,envp);
perror("execl error");
exit(0);
}
wait(NULL);
printf("main over\n");
exit(0);
}
新替换的 b 程序如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
int main(int argc, char* argv[],char* envp[])
{
printf("b pid=%d\n",getpid());
int i = 0;
printf("argc=%d\n",argc);
for( ; i < argc; i++ )
{
printf("argv[%d]=%s\n",i,argv[i]);
}
for( i = 0; envp[i] != NULL; i++ )
{
printf("envp[%d]=%s\n",i,envp[i]);
}
exit(0);
}
再举个例子
我们要把ps作为第一个参数,-f作为第二个参数
我们约定:传的第一个参数是当前进程的名字
main产生一个子进程,然后把子进程替换为ps