2010-06-12 123 views
5

我知道execve()和family要求其參數數組的第一個參數與第一個參數指向的可執行文件相同。也就是,在此:爲什麼第一個參數execve()必須是可執行文件的路徑

execve(prog, args, env); 

args [0]通常與prog相同。但我似乎無法找到關於這是爲什麼的信息。我也明白,可執行文件(呃,至少是shell腳本)在運行時總是有它們的調用路徑作爲第一個參數,但我會認爲shell會做這件事,而execve()會只需使用第一個參數(上面的「prog」)中給出的路徑調用可執行文件,然後像在命令行中那樣傳遞參數數組(從上面的「args」)....即,我沒有調用命令行上的腳本在args列表中具有重複的可執行文件路徑....

/bin/ls /bin/ls /home/john 

有人可以解釋嗎?

回答

4

它允許您指定要加載的可執行文件的確切路徑,但也允許在諸如pstop之類的工具中顯示「美化」名稱。

execl("/bin/ls", "ls", "/home/john", (char *)0); 
+2

您需要雙引號;並可能是一個空char *來終止參數列表,假設您使用的是execl()。 – 2010-06-12 03:28:26

+0

我會接受你的話,但有趣的是,我創建了一個測試,執行一個簡單的bash腳本,吐出$ 0,甚至當我使用「美化」程序名時,$ 0仍然是完整路徑execve()的第一個參數,那麼,我假設)。 – EBM 2010-06-12 03:30:32

+0

@Johnathan:怪罪Python。 – 2010-06-12 03:31:19

4

根據this,作爲程序名稱的第一個參數是一個自定義。

由定製時,第一元件應該是 執行的程序的(對於 例如,路徑的最後成分)

提到的名稱,這些值可以不同。例如,如果程序是從符號鏈接啓動的。程序名稱可能與用於啓動它的鏈接不同。

而且,你是對的。 shell通常會設置第一個參數。然而,在這種情況下,execve的使用完全避開了shell - 這就是爲什麼你需要自己設置它。

+0

感謝您的回答 – EBM 2010-06-12 03:28:54

9

不要求第一的論點承擔任何有關的可執行文件的名稱:

int main(void) 
{ 
    char *args[3] = { "rip van winkle", "30", 0 }; 
    execv("/bin/sleep", args); 
    return 1; 
} 

試試吧 - 在Mac上(後三項測試):

make x; ./x & sleep 1; ps 

在第三運行的輸出是:

MiniMac JL: make x; ./x & sleep 1; ps 
make: `x' is up to date. 
[3] 5557 
    PID TTY   TIME CMD 
5532 ttys000 0:00.04 -bash 
5549 ttys000 0:00.00 rip van winkle 30 
5553 ttys000 0:00.00 rip van winkle 30 
5557 ttys000 0:00.00 rip van winkle 30 
MiniMac JL: 

EBM評論:

呀,這使它更加怪異。在我的測試bash腳本(execve的目標)中,我沒有看到execve在arg [0]中的任何地方的價值 - 而不是在環境中,而不是$ 0。

修改實驗 - 一個名爲'bash的腳本。腳本':

#!/bin/bash 

echo "bash script at sleep (0: $0; *: $*)" 
sleep 30 

而修訂的計劃:

int main(void) 
{ 
    char *args[3] = { "rip van winkle", "30", 0 }; 
    execv("./bash.script", args); 
    return 1; 
} 

這就產生ps輸出:

bash script at sleep (0: ./bash.script; *: 30) 
    PID TTY   TIME CMD 
7804 ttys000 0:00.11 -bash 
7829 ttys000 0:00.00 /bin/bash ./bash.script 30 
7832 ttys000 0:00.00 sleep 30 

有兩種可能性,因爲我看到它:

  1. 內核在通過腳本執行腳本時會對命令行進行操作shebang('#!/bin/bash')行,或
  2. Bash本身與其參數列表沾在一起。

如何建立區別?我想複製殼的替代名稱,然後使用在家當替代名稱會告訴我們一些東西:

$ cp /bin/bash jiminy.cricket 
$ sed "s%/bin/bash%$PWD/jiminy.cricket%" bash.script > tmp 
$ mv tmp bash.script 
$ chmod +w bash.script 
$ ./x & sleep 1; ps 
[1] 7851 
bash script at sleep (0: ./bash.script; *: 30) 
    PID TTY   TIME CMD 
7804 ttys000 0:00.12 -bash 
7851 ttys000 0:00.01 /Users/jleffler/tmp/soq/jiminy.cricket ./bash.script 30 
7854 ttys000 0:00.00 sleep 30 
$ 

此,我認爲,表示所使用的家當機制,當內核重寫argv[0]


解決因nategoose評論:「#!/路徑/到/程序」

MiniMac JL: pwd 
/Users/jleffler/tmp/soq 
MiniMac JL: cat al.c 
#include <stdio.h> 
int main(int argc, char **argv) 
{ 
    while (*argv) 
     puts(*argv++); 
    return 0; 
} 
MiniMac JL: make al.c 
cc  al.c -o al 
MiniMac JL: ./al a b 'c d' e 
./al 
a 
b 
c d 
e 
MiniMac JL: cat bash.script 
#!/Users/jleffler/tmp/soq/al 

echo "bash script at sleep (0: $0; *: $*)" 
sleep 30 
MiniMac JL: ./x 
/Users/jleffler/tmp/soq/al 
./bash.script 
30 
MiniMac JL: 

這表明它是家當機制,而不是任何程序,如猛砸,即調整argv[0]的值。所以,執行二進制時,argv[0]的值不會被調整;當通過shebang執行腳本時,參數列表由內核調整; argv[0]是shebang上列出的二進制文件;如果在shebang之後有爭論,那就變成argv[1];下一個參數是腳本文件的名稱,後跟execv()或同等調用的其餘參數。

MiniMac JL: cat bash.script 
#!/Users/jleffler/tmp/soq/al -arg0 
#!/bin/bash 
#!/Users/jleffler/tmp/soq/jiminy.cricket 

echo "bash script at sleep (0: $0; *: $*)" 
sleep 30 
MiniMac JL: ./x 
/Users/jleffler/tmp/soq/al 
-arg0 
./bash.script 
30 
MiniMac JL: 
+0

是的,這使得它更奇怪。在我的測試bash腳本(execve的目標)中,我沒有看到execve在arg [0]中的任何地方的價值 - 而不是在環境中,而不是$ 0。 – EBM 2010-06-12 05:41:13

+0

製作腳本'#!/ home/me/print_args'並編寫一個簡單的打印arg程序,以確保誰使用'argv [0]'擺弄' – nategoose 2010-06-13 00:58:18

0

允許程序有許多名字和工作使用其名字,它被稱爲略有不同視。

成像微不足道的程序,例如print0.c編譯成print0:

#include <stdio.h> 
int main(int argc, char **argv) 
{ 
    printf("%s\n",argv[0]); 
    return 0; 
} 

運行它,./print0將打印./print0做一個符號鏈接例如打印1,現在使用名稱./print1來運行它 - 它會打印「./print1」。

現在,這是一個符號鏈接。但是使用exec *()函數,你可以明確地告訴程序的名字。

來自* NIX的神器,但很高興有。

+0

請參閱我對Jonathan Leffler的評論 - 使用測試bash腳本作爲目標execve調用,arg [0]不會出現在任何地方。也許一個C程序以不同的方式獲得它的參數,但至少對於一個bash腳本來說,你解釋的這個特性似乎是不存在的。 – EBM 2010-06-12 10:52:15

+0

是的,shell的exec不允許這樣做。人們不得不使用符號鏈接以不同的名稱調用程序。 – Dummy00001 2010-06-12 13:43:36

相關問題