execve函数

来源:互联网 发布:淘宝店铺产品怎么分类 编辑:程序博客网 时间:2024/04/28 17:11

虚拟存储器和存储器映射在程序加载到存储器的过程中扮演很关键的角色。execve函数在实际中如何加载和执行程序的呢?就是用到上边两个关键的概念。

exec簇函数,最后,都是调用了execve这个函数!

这个函数的作用,就是去执行一个文件!
典型的用法,就是在shell中,执行一个文件,比如说,一个编译好的文件,叫做helloworld,那么,在shell下执行./helloworld的时候,shell就去fork()一个子进程,然后在子进程里面execve("./helloworld",NULL,NULL);
这样,就执行了这个文件!
具体点:
在shell中:

if(!fork())
{
execve("./helloworld",NULL,NULL);
exit(0);
}

那么,这个execve函数,都做了什么,追一下内核看看!
首先,利用参数(文件名),调用函数namei(filename),能取得这个文件名对应的i节点!
然后把当前进程(子进程)的i节点置成上面取得的那个i节点。
释放所有资源,释放内存页表并且修改LDT。
凶狠的把中断压入的EIP的值都给改了,改成了从上面那个i节点读出的可执行文件的头部那个文件执行的头字段。
更猛的是,把栈也给改了!
好了,这下子跟父进程一点关系都没有了!
中断返回后,程序从i节点指向的那个可执行程序开始执行!
这里,我们注意到个问题!
execve之后,原来的那些代码,都没了,也就是说,上面的那个exit(0),根本执行不到那!因为在execve调用中,代码就换成了那个i节点的了,以前的那些,都释放了!牛!
于是,

#include <stdio.h>
#include <unistd.h>
int main()
{
execve("./helloworld",NULL,NULL);
printf("nothing!\n");
return 0;
}

这个程序输出什么?(假设helloworld程序输出hello world!)
那么,这个程序输出的,就是hello world!
你会想,为什么没有下面的nothing!啊?
因为,execve调用中,这些代码都没有了,代码被替换成helloworld的了,而且,只执行helloworld就完了!
那么,你会说,那怎么执行完helloworld后,继续做事啊?
这样!

#include <stdio.h>
#include <unistd.h>
int main()
{
if(!fork())
execve("./helloworld",NULL,NULL);
else
printf("nothing!\n");
return 0;
}

执行一下,绝大多数会输出hello world!后,输出nothing!
这个execve够变态!
但是,你会问,子程序执行完了,没有调用exit(0);资源如何回收啊?因为我们仅仅调用了个return 0;
这个问题问的好,在信号中呢,do_signal!下次继续探讨信号的问题!