exec簇函數(shù),最后,都是調(diào)用了execve這個(gè)函數(shù)!
這個(gè)函數(shù)的作用,就是去執(zhí)行一個(gè)文件!
典型的用法,就是在shell中,執(zhí)行一個(gè)文件,比如說,一個(gè)編譯好的文件,叫做helloworld,那么,在shell下執(zhí)行./helloworld的時(shí)候,shell就去fork()一個(gè)子進(jìn)程,然后在子進(jìn)程里面execve("./helloworld",NULL,NULL);
這樣,就執(zhí)行了這個(gè)文件!
具體點(diǎn):
在shell中:
if(!fork())
{
execve("./helloworld",NULL,NULL);
exit(0);
}
那么,這個(gè)execve函數(shù),都做了什么,追一下內(nèi)核看看!
首先,利用參數(shù)(文件名),調(diào)用函數(shù)namei(filename),能取得這個(gè)文件名對(duì)應(yīng)的i節(jié)點(diǎn)!
然后把當(dāng)前進(jìn)程(子進(jìn)程)的i節(jié)點(diǎn)置成上面取得的那個(gè)i節(jié)點(diǎn)。
釋放所有資源,釋放內(nèi)存頁(yè)表并且修改LDT。
兇狠的把中斷壓入的EIP的值都給改了,改成了從上面那個(gè)i節(jié)點(diǎn)讀出的可執(zhí)行文件的頭部那個(gè)文件執(zhí)行的頭字段。
更猛的是,把棧也給改了!
好了,這下子跟父進(jìn)程一點(diǎn)關(guān)系都沒有了!
中斷返回后,程序從i節(jié)點(diǎn)指向的那個(gè)可執(zhí)行程序開始執(zhí)行!
這里,我們注意到個(gè)問題!
execve之后,原來的那些代碼,都沒了,也就是說,上面的那個(gè)exit(0),根本執(zhí)行不到那!因?yàn)樵趀xecve調(diào)用中,代碼就換成了那個(gè)i節(jié)點(diǎn)的了,以前的那些,都釋放了!牛!
于是,
#include <stdio.h>
#include <unistd.h>
int main()
{
execve("./helloworld",NULL,NULL);
printf("nothing!\n");
return 0;
}
這個(gè)程序輸出什么?(假設(shè)helloworld程序輸出hello world?。?/div>
那么,這個(gè)程序輸出的,就是hello world!
你會(huì)想,為什么沒有下面的nothing!啊?
因?yàn)椋琫xecve調(diào)用中,這些代碼都沒有了,代碼被替換成helloworld的了,而且,只執(zhí)行helloworld就完了!
那么,你會(huì)說,那怎么執(zhí)行完helloworld后,繼續(xù)做事???
這樣!
#include <stdio.h>
#include <unistd.h>
int main()
{
if(!fork())
execve("./helloworld",NULL,NULL);
else
printf("nothing!\n");
return 0;
}
執(zhí)行一下,絕大多數(shù)會(huì)輸出hello world!后,輸出nothing!
這個(gè)execve夠變態(tài)!
但是,你會(huì)問,子程序執(zhí)行完了,沒有調(diào)用exit(0);資源如何回收???因?yàn)槲覀儍H僅調(diào)用了個(gè)return 0;
這個(gè)問題問的好,在信號(hào)中呢,do_signal!下次繼續(xù)探討信號(hào)的問題!