2013-01-13 215 views
20

我知道execvp可用於執行簡單的命令如下:execvp如何運行命令?

char* arg[] = {"ls", "-l", NULL}; 
execvp(arg[0],arg); 

我想知道這裏繼續當我運行execvp。在手冊頁中,它表示execvp用新的圖像替換過程映像的圖像。但是,我在這裏運行的命令不是可執行文件。

具體而言,說有特異性需要輸入例如一個命令貓。如果我有一個包含預期貓文件名的文本文件的text.txt和我標準輸入重定向到文件的文件流,會的execle("cat","cat",NULL)execvp("cat", arg)輸出(當然其中arg店"cat"NULL)結果的輸出控制檯作爲cat /filename會?我的直覺是我必須閱讀該文件,並可能會解析它以將參數存儲在arg中。但是我想確認一下。

在此先感謝!

+1

linux中的所有命令都是可執行文件。 – Alex

+2

在終端輸入'ls'來查看'ls'程序的位置。當你說'ls'時,你確實正在運行一個可執行文件。 – Cornstalks

+1

@Alex:除了在shell中實現的一些特殊命令外,例如'cd','source'和'exit'。 – duskwuff

回答

16

下面是一個execvp呼叫發生的事情:在PATH

  1. 你的libc實現搜索,如果適用,因爲這是要執行的文件。類UNIX系統中的大多數(如果不是全部)命令都是可執行文件。如果不是,會發生什麼?嘗試一下。看看how glibc does it
  2. 通常情況下,如果找到可執行文件,將致電execveexecve的部分可以在libc中實現,也可以是系統調用(就像在Linux中一樣)。
  3. 的Linux由爲它分配內存,打開它,調度它用於執行,初始化存儲器結構準備的程序,從所提供的參數傳遞給execvp呼叫建立它的參數和環境,發現適當的處理程序,用於加載的二進制,和將當前任務(execvp調用者)設置爲不執行。你可以找到它的實現here

以上所有步驟均符合相關的manual pages中描述的POSIX要求。

+0

真棒解釋!一個小小的懷疑 - 是否意味着裝載的新圖像將具有與舊圖像相同的CR3值? –

+0

不可以。每個進程都有自己的CR3,這是設置頁表的代碼的責任。 –

2

「LS」不僅僅是一個命令,它實際上是一個程序(大部分命令)。當你像這樣運行execvp時,它會將你的整個程序,內存,堆棧,堆等等從核心中清除出去,從概念上「清除掉」並將它提供給「ls」,以便它可以將它用於自己的堆棧,堆等

總之,execvp會破壞你的計劃,並代之以另一項計劃是,在這種情況下,「LS」。

+0

爲什麼降低投票率? – Alex

+0

不確定...看起來像某人只是upvoted它回到0雖然哈哈。 – Verdagon

1

我的直覺是我必須閱讀該文件,並可能會解析它以將參數存儲在arg中。但是我想確認一下。

你的直覺是正確的大部分。該cat實用工具,您使用作爲一個例子有兩個單獨的代碼路徑:

  • 如果有作爲參數指定的文件名,它會打開並閱讀各一轉。
  • 如果沒有指定文件名,它將從標準輸入讀取。

此行爲專門在cat實用程序中實現 - 它未在任何較低級別實施。尤其是,它絕對不是系統調用exec的一部分。系統調用exec根本不「看」論據;他們只是將它們直接傳遞給argv中的新進程,然後該進程可以處理它們,但它看起來合適。

12

關於你的問題:

在手冊頁它說execvp替換過程映像 的形象與新的。但是,在這裏我運行的命令不是 可執行文件。

很久以前的shell非常有限,幾乎所有的UNIX命令都是獨立的可執行文件。現在,主要爲了速度的目的,UNIX命令的一些子集是在shell本身內部實現的,那些命令被稱爲builtins。您可以檢查任何命令在你的shell內置的或無法通過type命令來實現:

λ ~/ type echo 
echo is a shell builtin 

(帶有介紹內建的完整列表可在man頁面,你的shell如man bash-builtinsman builtin找到)

但仍然大部分的命令仍然有其可執行文件,對應:

λ ~/ whereis echo 
/bin/echo 

因此,在特定情況下,當你正在運行:

char* arg[] = {"ls", "-l", NULL}; 
execvp(arg[0],arg); 

你實際上是用的(最有可能)/bin/ls地址空間替代當前進程的地址空間。


我的直覺是我要讀文件,並且可以解析它來存儲 參數在ARG。

確實,你有。但你也可以使用一些內核函數爲又名「家當」:
而不是把文件名在單獨文件中添加所謂的家當作爲文件的第一行要貓:

#!/bin/cat 

並添加chmod +x它。然後,你可以爲可執行文件(通過任何的exec功能或外殼)運行:

λ ~/tmp/ printf '#!/bin/cat\nTEST\n' > cat_me 
λ ~/tmp/ chmod +x cat_me 
λ ~/tmp/ ./cat_me 
#!/bin/cat 
TEST 

原因是與文件打印shebang自身的缺點,但它仍然是有趣的事情是在內核=)

順便說一句。您描述的問題,如果很常見,以至於有一個稱爲xargs的特殊可執行文件(在非常簡單的解釋中)執行通過stdin傳遞的參數列表上的給定程序。欲瞭解更多信息,請諮詢man xargs


對於exec容易記憶 - 家庭我經常使用下表:

  Figure 8.14. Differences among the six exec functions 
+----------+----------+----------+----------+--------+---------+--------+ 
| Function | pathname | filename | agr list | argv[] | environ | envp[] | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execl | *  |   |  * |  | * |  | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execlp |   | *  |  * |  | * |  | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execle | *  |   |  * |  |   | * | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execv | *  |   |   | * | * |  | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execvp |   | *  |   | * | * |  | 
+----------+----------+----------+----------+--------+---------+--------+ 
| execve | *  |   |   | * |   | * | 
+----------+----------+----------+----------+--------+---------+--------+ 
| letter |   | p  |  l | v |   | e | 
+----------+----------+----------+----------+--------+---------+--------+ 

所以你的情況execvp需要的文件名,argv(包含v)和environ(ê)。 然後它試圖通過將filename(在您的案例cat中)附加到PATH中的每個路徑組件來「猜測」路徑名(又名完整路徑),直到找到可執行文件filename的路徑。

更多關於exec的引擎蓋(包括繼承材料)的更多信息可以在Advanced Programming in the UNIX Environment (2nd Edition) by W. Richard Stevens and Stephen A. Rago又名APUE2中找到。
如果您對UNIX內部感興趣,您應該閱讀它。