- 論壇徽章:
- 0
|
Linux中的system函數(shù)詳細(xì)分析system()函數(shù)功能強(qiáng)大,很多人用卻對它的原理知之甚少,也就有了上面
那么多的回帖,我想大家如果知道了system的具體實(shí)現(xiàn)就不會(huì)對樓主程序在很多編譯器中不能表現(xiàn)自己希望的功能感到費(fèi)解了。我對linux中的實(shí)現(xiàn)比較
了解,具體分析這個(gè),windows中的類似就不詳解了。
好了,先看linux版system函數(shù)的源碼:- #include
- #include
- #include
- #include
- int system(const char * cmdstring)
- {
- pid_t pid;
- int status;
- if(cmdstring == NULL){
-
- return (1);
- }
- if((pid = fork())<0){
- status = -1;
- }
- else if(pid == 0){
- execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
- -exit(127); //子進(jìn)程正常執(zhí)行則不會(huì)執(zhí)行此語句
- }
- else{
- while(waitpid(pid, &status, 0) < 0){
- if(errno != EINTER){
- status = -1;
- break;
- }
- }
- }
- return status;
- }
復(fù)制代碼 先分析一下原理,然后再看上面的代碼大家估計(jì)就能看懂了:
當(dāng)system接受的命令為NULL時(shí)直接返回,否則fork出一個(gè)子進(jìn)程,因?yàn)閒ork在兩個(gè)進(jìn)程:父進(jìn)程和子進(jìn)程中都返回,這里要檢查返回的
pid,fork在子進(jìn)程中返回0,在父進(jìn)程中返回子進(jìn)程的pid,父進(jìn)程使用waitpid等待子進(jìn)程結(jié)束,子進(jìn)程則是調(diào)用execl來啟動(dòng)一個(gè)程序代
替自己,execl("/bin/sh", "sh", "-c",
cmdstring,(char*)0)是調(diào)用shell,這個(gè)shell的路徑是/bin/sh,后面的字符串都是參數(shù),然后子進(jìn)程就變成了一個(gè)
shell進(jìn)程,這個(gè)shell的參數(shù)是cmdstring,就是system接受的參數(shù)。在windows中的shell是command,想必大家很
熟悉shell接受命令之后做的事了。
如果上面的你沒有看懂,那我再解釋下fork的原理:當(dāng)一個(gè)進(jìn)程A調(diào)用fork時(shí),系統(tǒng)內(nèi)核創(chuàng)建一個(gè)新的進(jìn)程B,并將A的內(nèi)存映像復(fù)制到B的進(jìn)程空間中,
因?yàn)锳和B是一樣的,那么他們怎么知道自己是父進(jìn)程還是子進(jìn)程呢,看fork的返回值就知道,上面也說了fork在子進(jìn)程中返回0,在父進(jìn)程中返回子進(jìn)程
的pid。
windows中的情況也類似,就是execl換了個(gè)又臭又長的名字,參數(shù)名也換的看了讓人發(fā)暈的,我在MSDN中找到了原型,給大家看看:
HINSTANCE ShellExecute(
HWND hwnd,
LPCTSTR lpVerb,
LPCTSTR lpFile,
LPCTSTR lpParameters,
LPCTSTR lpDirectory,
INT nShowCmd
);
用法如下:
ShellExecute(NULL, "open", "c:\\a.reg", NULL, NULL, SW_SHOWNORMAL);
你也許會(huì)奇怪 ShellExecute中有個(gè)用來傳遞父進(jìn)程環(huán)境變量的參數(shù)
lpDirectory,linux中的execl卻沒有,這是因?yàn)閑xecl是編譯器的函數(shù)(在一定程度上隱藏具體系統(tǒng)實(shí)現(xiàn)),在linux中它會(huì)接著
產(chǎn)生一個(gè)linux系統(tǒng)的調(diào)用execve, 原型見下:
int execve(const char * file,const char **argv,const char **envp);
看到這里你就會(huì)明白為什么system()會(huì)接受父進(jìn)程的環(huán)境變量,但是用system改變環(huán)境變量后,system一返回主函數(shù)還是沒變,這就是我在
22樓反復(fù)強(qiáng)調(diào)的。原因從system的實(shí)現(xiàn)可以看到,它是通過產(chǎn)生新進(jìn)程實(shí)現(xiàn)的,從我的分析中可以看到父進(jìn)程和子進(jìn)程間沒有進(jìn)程通信,子進(jìn)程自然改變不
了父進(jìn)程的環(huán)境變量。希望小菜們不要拿tc或使用tc庫的其他編譯器中的system的調(diào)用結(jié)果來反駁我,這不是一個(gè)概念,DOS早死翹翹了,玩
linux吧。就說到這里了。
本文來自ChinaUnix博客,如果查看原文請點(diǎn):http://blog.chinaunix.net/u2/66576/showart_2056977.html |
|