青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Prayer

在一般中尋求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

exec函數族

Posted on 2009-09-18 11:20 Prayer 閱讀(512) 評論(0)  編輯 收藏 引用 所屬分類: LINUX/UNIX/AIX
exec函數族

也許有不少讀者從本系列文章一推出就開始讀,一直到這里還有一個很大的疑惑:既然所有新進程都是由fork產生的,而且由fork產生的子進程和父進程幾乎完全一樣,那豈不是意味著系統中所有的進程都應該一模一樣了嗎?而且,就我們的常識來說,當我們執行一個程序的時候,新產生的進程的內容應就是程序的內容才對。是我們理解錯了嗎?顯然不是,要解決這些疑惑,就必須提到我們下面要介紹的exec系統調用。

1.10.1 簡介

說是exec系統調用,實際上在Linux中,并不存在一個exec()的函數形式,exec指的是一組函數,一共有6個,分別是:

#include <unistd.h>
            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 execve(const char *path, char *const argv[], char *const envp[]);
            

其中只有execve是真正意義上的系統調用,其它都是在此基礎上經過包裝的庫函數。

exec函數族的作用是根據指定的文件名找到可執行文件,并用它來取代調用進程的內容,換句話說,就是在調用進程內部執行一個可執行文件。這里的可執行文件既可以是二進制文件,也可以是任何Linux下可執行的腳本文件。

與一般情況不同,exec函數族的函數執行成功后不會返回,因為調用進程的實體,包括代碼段,數據段和堆棧等都已經被新的內容取代,只留下進程ID等一些表面上的信息仍保持原樣,頗有些神似"三十六計"中的"金蟬脫殼"。看上去還是舊的軀殼,卻已經注入了新的靈魂。只有調用失敗了,它們才會返回一個-1,從原程序的調用點接著往下執行。

現在我們應該明白了,Linux下是如何執行新程序的,每當有進程認為自己不能為系統和擁護做出任何貢獻了,他就可以發揮最后一點余熱,調用任何一個exec,讓自己以新的面貌重生;或者,更普遍的情況是,如果一個進程想執行另一個程序,它就可以fork出一個新進程,然后調用任何一個exec,這樣看起來就好像通過執行應用程序而產生了一個新進程一樣。

事實上第二種情況被應用得如此普遍,以至于Linux專門為其作了優化,我們已經知道,fork會將調用進程的所有內容原封不動的拷貝到新產生的子進程中去,這些拷貝的動作很消耗時間,而如果fork完之后我們馬上就調用exec,這些辛辛苦苦拷貝來的東西又會被立刻抹掉,這看起來非常不劃算,于是人們設計了一種"寫時拷貝(copy-on-write)"技術,使得fork結束后并不立刻復制父進程的內容,而是到了真正實用的時候才復制,這樣如果下一條語句是exec,它就不會白白作無用功了,也就提高了效率。

1.10.2 稍稍深入

上面6條函數看起來似乎很復雜,但實際上無論是作用還是用法都非常相似,只有很微小的差別。在學習它們之前,先來了解一下我們習以為常的main函數。

下面這個main函數的形式可能有些出乎我們的意料:

int main(int argc, char *argv[], char *envp[])
            

它可能與絕大多數教科書上描述的都不一樣,但實際上,這才是main函數真正完整的形式。

參數argc指出了運行該程序時命令行參數的個數,數組argv存放了所有的命令行參數,數組envp存放了所有的環境變量。環境變量指的是一組值,從用戶登錄后就一直存在,很多應用程序需要依靠它來確定系統的一些細節,我們最常見的環境變量是PATH,它指出了應到哪里去搜索應用程序,如/bin;HOME也是比較常見的環境變量,它指出了我們在系統中的個人目錄。環境變量一般以字符串"XXX=xxx"的形式存在,XXX表示變量名,xxx表示變量的值。

值得一提的是,argv數組和envp數組存放的都是指向字符串的指針,這兩個數組都以一個NULL元素表示數組的結尾。

我們可以通過以下這個程序來觀看傳到argc、argv和envp里的都是什么東西:

/* main.c */
            int main(int argc, char *argv[], char *envp[])
            {
            printf("\n### ARGC ###\n%d\n", argc);
            printf("\n### ARGV ###\n");
            while(*argv)
            printf("%s\n", *(argv++));
            printf("\n### ENVP ###\n");
            while(*envp)
            printf("%s\n", *(envp++));
            return 0;
            }
            

編譯它:

$ cc main.c -o main
            

運行時,我們故意加幾個沒有任何作用的命令行參數:

$ ./main -xx 000
            ### ARGC ###
            3
            ### ARGV ###
            ./main
            -xx
            000
            ### ENVP ###
            PWD=/home/lei
            REMOTEHOST=dt.laser.com
            HOSTNAME=localhost.localdomain
            QTDIR=/usr/lib/qt-2.3.1
            LESSOPEN=|/usr/bin/lesspipe.sh %s
            KDEDIR=/usr
            USER=lei
            LS_COLORS=
            MACHTYPE=i386-redhat-linux-gnu
            MAIL=/var/spool/mail/lei
            INPUTRC=/etc/inputrc
            LANG=en_US
            LOGNAME=lei
            SHLVL=1
            SHELL=/bin/bash
            HOSTTYPE=i386
            OSTYPE=linux-gnu
            HISTSIZE=1000
            TERM=ansi
            HOME=/home/lei
            PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/lei/bin
            _=./main
            

我們看到,程序將"./main"作為第1個命令行參數,所以我們一共有3個命令行參數。這可能與大家平時習慣的說法有些不同,小心不要搞錯了。

現在回過頭來看一下exec函數族,先把注意力集中在execve上:

int execve(const char *path, char *const argv[], char *const envp[]);
            

對比一下main函數的完整形式,看出問題了嗎?是的,這兩個函數里的argv和envp是完全一一對應的關系。execve第1個參數path是被執行應用程序的完整路徑,第2個參數argv就是傳給被執行應用程序的命令行參數,第3個參數envp是傳給被執行應用程序的環境變量。

留心看一下這6個函數還可以發現,前3個函數都是以execl開頭的,后3個都是以execv開頭的,它們的區別在于,execv開頭的函數是以"char *argv[]"這樣的形式傳遞命令行參數,而execl開頭的函數采用了我們更容易習慣的方式,把參數一個一個列出來,然后以一個NULL表示結束。這里的NULL的作用和argv數組里的NULL作用是一樣的。

在全部6個函數中,只有execle和execve使用了char *envp[]傳遞環境變量,其它的4個函數都沒有這個參數,這并不意味著它們不傳遞環境變量,這4個函數將把默認的環境變量不做任何修改地傳給被執行的應用程序。而execle和execve會用指定的環境變量去替代默認的那些。

還有2個以p結尾的函數execlp和execvp,咋看起來,它們和execl與execv的差別很小,事實也確是如此,除execlp和execvp之外的4個函數都要求,它們的第1個參數path必須是一個完整的路徑,如"/bin/ls";而execlp和execvp的第1個參數file可以簡單到僅僅是一個文件名,如"ls",這兩個函數可以自動到環境變量PATH制定的目錄里去尋找。

1.10.3 實戰

知識介紹得差不多了,接下來我們看看實際的應用:

/* exec.c */
            #include <unistd.h>
            main()
            {
            char *envp[]={"PATH=/tmp",
            "USER=lei",
            "STATUS=testing",
            NULL};
            char *argv_execv[]={"echo", "excuted by execv", NULL};
            char *argv_execvp[]={"echo", "executed by execvp", NULL};
            char *argv_execve[]={"env", NULL};
            if(fork()==0)
            if(execl("/bin/echo", "echo", "executed by execl", NULL)<0)
            perror("Err on execl");
            if(fork()==0)
            if(execlp("echo", "echo", "executed by execlp", NULL)<0)
            perror("Err on execlp");
            if(fork()==0)
            if(execle("/usr/bin/env", "env", NULL, envp)<0)
            perror("Err on execle");
            if(fork()==0)
            if(execv("/bin/echo", argv_execv)<0)
            perror("Err on execv");
            if(fork()==0)
            if(execvp("echo", argv_execvp)<0)
            perror("Err on execvp");
            if(fork()==0)
            if(execve("/usr/bin/env", argv_execve, envp)<0)
            perror("Err on execve");
            }
            

程序里調用了2個Linux常用的系統命令,echo和env。echo會把后面跟的命令行參數原封不動的打印出來,env用來列出所有環境變量。

由于各個子進程執行的順序無法控制,所以有可能出現一個比較混亂的輸出--各子進程打印的結果交雜在一起,而不是嚴格按照程序中列出的次序。

編譯并運行:

$ cc exec.c -o exec
            $ ./exec
            executed by execl
            PATH=/tmp
            USER=lei
            STATUS=testing
            executed by execlp
            excuted by execv
            executed by execvp
            PATH=/tmp
            USER=lei
            STATUS=testing
            

果然不出所料,execle輸出的結果跑到了execlp前面。

大家在平時的編程中,如果用到了exec函數族,一定記得要加錯誤判斷語句。因為與其他系統調用比起來,exec很容易受傷,被執行文件的位置,權限等很多因素都能導致該調用的失敗。最常見的錯誤是:

  1. 找不到文件或路徑,此時errno被設置為ENOENT;
  2. 數組argv和envp忘記用NULL結束,此時errno被設置為EFAULT;
  3. 沒有對要執行文件的運行權限,此時errno被設置為EACCES。
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲黄色视屏| 老牛国产精品一区的观看方式| 欧美日韩在线观看视频| 久久爱另类一区二区小说| 亚洲黄网站在线观看| 欧美日韩不卡一区| 欧美国产一区二区在线观看| 久久国产精品免费一区| 欧美日本三区| 国产精品观看| 欧美三级在线视频| 国产精品成人免费| 一本色道婷婷久久欧美| 亚洲区一区二| 99在线观看免费视频精品观看| 久久久久久69| 久久久久久久性| 亚洲影院色无极综合| 亚洲欧美影音先锋| 亚洲欧美另类在线| 午夜精品免费视频| 亚洲最新合集| 亚洲香蕉成视频在线观看| 一本大道久久a久久精二百| 欧美成人精品不卡视频在线观看 | 久久久久高清| 免费永久网站黄欧美| 欧美精品综合| 一区二区三区欧美亚洲| 亚洲女人小视频在线观看| 香港久久久电影| 久久国产精品久久久久久久久久 | 欧美亚洲一区二区在线观看| 一本色道久久综合亚洲精品小说| 亚洲欧美日韩成人| 国产亚洲一区在线播放| 亚洲福利视频在线| 一区二区三区欧美日韩| 99亚洲一区二区| 亚洲第一黄网| av成人毛片| 91久久在线观看| 欧美精品日韩| 激情一区二区| 日韩亚洲欧美成人| 欧美专区日韩专区| 欧美激情欧美激情在线五月| 亚洲日本成人| 久久xxxx精品视频| 欧美激情精品久久久久久| 99在线热播精品免费99热| 99人久久精品视频最新地址| 国产日韩精品电影| 一区二区三区产品免费精品久久75| 日韩午夜在线| 欧美jizz19性欧美| 西瓜成人精品人成网站| 久久精品在线观看| 国产欧美日韩视频| 欧美成va人片在线观看| 亚洲欧美国产毛片在线| 亚洲国产一区二区a毛片| 亚洲尤物视频网| 99精品欧美一区二区三区综合在线| 亚洲日本在线观看| 国内久久精品| 久久成人精品视频| 欧美精品播放| 欧美中文在线字幕| 欧美精品一区二区三区一线天视频| 久久不射网站| 欧美日韩色一区| 久久综合久久美利坚合众国| 欧美在线啊v| 亚洲视频导航| 91久久在线播放| 国产综合色一区二区三区| 亚洲三级影院| 亚洲欧洲日韩在线| 久久精品视频免费观看| 亚洲欧美综合另类中字| 亚洲欧美日韩成人高清在线一区| 亚洲国产精品成人一区二区| 亚洲永久精品国产| 亚洲精品国产拍免费91在线| 噜噜噜噜噜久久久久久91| 久久久久久久久久久久久9999| 亚洲欧美影音先锋| 欧美三级日本三级少妇99| 亚洲第一久久影院| 久久久不卡网国产精品一区| 亚洲一区二区av电影| 亚洲一区二区三区在线视频| 日韩西西人体444www| 久久婷婷麻豆| 亚洲国产日韩精品| 久久久久综合网| 麻豆成人精品| 狠狠做深爱婷婷久久综合一区| 裸体丰满少妇做受久久99精品| 国产日产欧美精品| 午夜视频久久久久久| 国产精品一区二区久久久久| 国产精品免费福利| 亚洲欧美另类久久久精品2019| 欧美激情精品久久久久久变态| 亚洲国产成人久久| 一本大道久久a久久综合婷婷 | 欧美中文字幕视频在线观看| 欧美在线你懂的| 国产日韩欧美一区二区三区四区| 久久久久久国产精品mv| 国产亚洲欧美一区在线观看| 午夜日韩电影| 欧美黄色aa电影| 一本色道久久综合亚洲二区三区| 欧美天堂亚洲电影院在线播放| 一区二区三区日韩精品视频| 久久电影一区| 亚洲国产精品一区二区www| 久久青草欧美一区二区三区| 亚洲高清123| 亚洲欧洲精品天堂一级| 一区二区三欧美| 欧美一区在线直播| 免费看成人av| 欧美大秀在线观看| 欧美日韩在线精品| 亚洲国产欧美在线| 国产精品一二三视频| 亚洲手机视频| 久久综合国产精品台湾中文娱乐网| 亚洲经典三级| 国产精品乱人伦中文| 久久亚洲视频| 亚洲视频在线观看一区| 久久一区亚洲| 一二三区精品福利视频| 国产精品久久久久久亚洲毛片 | 亚洲欧美三级伦理| 久久这里只有精品视频首页| 一区二区国产精品| 激情综合视频| 国产精品久久久久久久久婷婷 | 国产日韩在线不卡| 欧美成人亚洲成人日韩成人| aa级大片欧美| 欧美成人伊人久久综合网| 午夜国产一区| 亚洲三级视频在线观看| 国产精品亚洲不卡a| 91久久精品www人人做人人爽| 亚洲天堂第二页| 在线成人www免费观看视频| 一区二区三区四区在线| 亚洲人成7777| 国产伦精品一区二区三区在线观看| 久久女同精品一区二区| 亚洲性视频网站| 亚洲国产精品尤物yw在线观看 | 亚洲黄色一区二区三区| 欧美一区二区三区的| 亚洲欧洲一区| 影音先锋成人资源站| 国产人成精品一区二区三| 欧美在线视频导航| 一区二区三区欧美| 亚洲精品男同| 亚洲电影下载| 在线免费不卡视频| 伊人久久综合| 精品动漫3d一区二区三区| 国产精品最新自拍| 国产精品视频在线观看| 国产精品亚洲精品| 国产精品久久久久高潮| 欧美三级第一页| 欧美特黄一级大片| 欧美视频福利| 国产精品无人区| 国产日韩在线一区二区三区| 国产麻豆精品在线观看| 国产日韩欧美一区二区三区在线观看| 国产欧美1区2区3区| 国产一区二区三区免费不卡| 国产综合色在线| 亚洲黄色在线观看| 亚洲美女91| 国产精品美女久久久久av超清| 欧美日韩一区二区三区在线看 | 欧美午夜精品伦理| 久久精品国产综合精品| 欧美在线视频观看| 噜噜噜久久亚洲精品国产品小说| 亚洲免费观看| 中文精品视频| 久久精品国产96久久久香蕉| 免费观看在线综合色| 欧美日韩精品免费观看视频| 国产精品久久久久久久久婷婷|