Typowe programy uniksowe / Linux akceptują dane z wiersza poleceń jako argument count ( int argc
) i wektor argumentu ( char *argv[]
). Pierwszym elementem argv
jest nazwa programu - po nim rzeczywiste argumenty.
Dlaczego nazwa programu jest przekazywana do pliku wykonywalnego jako argument? Czy są jakieś przykłady programów używających ich własnych nazw (może jakaś exec
sytuacja)?
command-line
c
arguments
Shrikant Giridhar
źródło
źródło
sh
jest dowiązanie symbolicznedash
. Zachowują się inaczej, gdy są nazywani jakosh
lub jakodash
busybox
( typowego na dyskach ratunkowych itp. ), To prawie wszystko (cp, mv, rm, ls, ...) jest dowiązaniem symbolicznym do busybox.gcc
,bash
,gunzip
, większość z resztą OS ...), jak Linux to tylko jądro.Odpowiedzi:
Na początek zauważ, że
argv[0]
niekoniecznie jest to nazwa programu. To jest to, co rozmówca kładzie sięargv[0]
naexecve
wywołanie systemowe (np patrz na to pytanie na przepełnienie stosu ). (Wszystkie inne wariantyexec
nie są wywołaniami systemowymi, ale interfejsami doexecve
.)Załóżmy na przykład, że (używając
execl
):/var/tmp/mybackdoor
to, co jest wykonywane, aleargv[0]
jest ustawione natop
, i to właśnie wyświetlips
lub (rzeczywiste)top
. Zobacz tę odpowiedź na U&L SE, aby uzyskać więcej na ten temat.Odkładając to wszystko na bok: Przed pojawieniem się takich fantazyjnych systemów plików
/proc
,argv[0]
był to jedyny sposób, aby proces poznał własną nazwę. Do czego to by było dobre?źródło
bunzip2
,bzcat
ibzip2
, dla których dwa pierwsze są dowiązania do trzeciego.zcat
nie jest dowiązaniem symbolicznym. Wydaje się, że unikają wad tej techniki, używając skryptu powłoki. Nie udaje im się jednak wydrukować pełnego--help
wyniku, ponieważ ktoś, kto dodał opcje do gzip, również zapomniał zachować Zcat.gunzip
jest historycznym wyjątkiem.argv[0]
dane wyjściowe dotyczące użycia / pomocy zamiast na stałe kodować ich nazwy. Niektóre w całości, niektóre tylko basename.Dużo:
argv[0]
jestsh
. Działa jako powłoki logowania, gdyargv[0]
rozpoczyna się-
.vi
,view
,evim
,eview
,ex
,vimdiff
, itd.shutdown
,reboot
itp są dowiązania dosystemctl
.źródło
sendmail
imail
. Każdy MTA uniksowy zawiera łącze symboliczne dla tych dwóch poleceń i ma na celu emulację zachowania oryginału, gdy zostanie wywołany, co oznacza, że każdy program uniksowy, który musi wysłać pocztę, wie dokładnie, jak to zrobić.test
i[
: kiedy wywołujesz ten pierwszy, obsługuje błąd, jeśli ostatnim argumentem jest]
. (w aktualnej stabilnej wersji Debiana polecenia te są dwoma różnymi programami, ale poprzednie wersje i MacO nadal używają tego samego programu). Atex
,latex
i tak dalej: binarna jest taka sama, ale patrząc, jak to nazwano, to wybrać odpowiednią konfigurację pliku.init
jest podobny.[
uważa to za błąd, jeśli ostatni argument nie jest]
.Historycznie
argv
jest to tylko tablica wskaźników do „słów” wiersza poleceń, więc warto zacząć od pierwszego „słowa”, którym jest nazwa programu.Jest też sporo programów, które zachowują się inaczej, w zależności od tego, do jakiej nazwy się je wywołuje, więc możesz po prostu tworzyć do nich różne łącza i uzyskiwać różne „polecenia”. Najbardziej ekstremalnym przykładem, jaki mogę wymyślić, jest busybox , który działa jak kilkadziesiąt różnych „poleceń” w zależności od tego, jak się nazywa .
Edycja : Referencje dla 1. edycji Uniksa, zgodnie z żądaniem
Widać np. Z głównej funkcji
cc
tegoargc
iargv
były już używane. Te powłoki kopiuje argumentów doparbuf
wewnątrznewarg
części pętli, traktując ten sam rozkaz w taki sam sposób, jak argumentów. (Oczywiście później wykonuje tylko pierwszy argument, którym jest nazwa polecenia). Wygląda na to, żeexecv
krewni wtedy nie istnieli.źródło
exec
pobiera nazwę polecenia do wykonania i tablicę wskaźników charczących zero (najlepiej widać na minnie.tuhs.org/cgi-bin/utree.pl?file=V1/u0.s , gdzieexec
bierze2:
pojawiają się odniesienia do etykiety 2 i etykiety 1, a na etykiecieetc/init\0
, a na etykiecie1:
pojawia się odniesienie do etykiety 2 i zera kończącego), co jest w zasadzie tym, coexecve
dziś minusenvp
.execv
iexecl
istniały „na zawsze” (tj. od początku do połowy lat 70.) -execv
było wywołaniem systemowym iexecl
było funkcją biblioteki, która je wywołała.execve
wtedy nie istniało, ponieważ wtedy środowisko nie istniało. Pozostali członkowie rodziny zostali dodani później.execv
źródło v1, które podłączyłem? Po prostu ciekawy.Przypadków użycia:
Możesz użyć nazwy programu aby zmienić zachowanie programu .
Na przykład możesz utworzyć dowiązania symboliczne do rzeczywistego pliku binarnego.
Jednym znanym przykładem zastosowania tej techniki jest projekt busybox, który instaluje tylko jeden plik binarny i wiele dowiązań symbolicznych do niego. (ls, cp, mv itp.). Oni to robią aby zaoszczędzić miejsce, ponieważ ich celem są małe urządzenia wbudowane.
Jest to również używane w programie
setarch
util-linux:Tutaj używają tej techniki w zasadzie aby uniknąć wielu zduplikowanych plików źródłowych lub po prostu, aby źródła były bardziej czytelne.
Innym przykładem użycia może być program, który musi załadować niektóre moduły lub dane w czasie wykonywania. Posiadanie ścieżki programu pozwala ładowanie modułów ze ścieżki względem lokalizacji programu .
Ponadto wiele programów drukuje komunikaty o błędach, w tym nazwę programu .
Dlaczego :
man 3p execve
):Zauważ, że C Standard mówi „nazwa programu”, a nie „nazwa pliku”.
źródło
Oprócz programów zmieniających ich zachowanie w zależności od tego, jak zostały wywołane, uważam, że
argv[0]
przydatne w drukowaniu użycia programu, takie jak:To powoduje, że komunikat użycia zawsze używa nazwy, przez którą został wywołany. Jeśli nazwa programu zostanie zmieniona, jego komunikat o użyciu zmienia się wraz z nim. Zawiera nawet nazwę ścieżki, z którą został wywołany:
To miły akcent, szczególnie w przypadku małych narzędzi / skryptów specjalnego przeznaczenia, które mogą istnieć wszędzie.
Wydaje się to powszechną praktyką również w narzędziach GNU, patrz
ls
na przykład:źródło
Jeden wykonuje pisanie programu:
program_name0 arg1 arg2 arg3 ...
.Więc powłoka powinna już podzielić token, a pierwszy token jest już nazwą programu. I BTW, więc są te same wskaźniki po stronie programu i powłoki.
Myślę, że to była tylko sztuczka wygody (na samym początku) i, jak widać w innych odpowiedziach, była również bardzo przydatna, więc ta tradycja była kontynuowana i ustawiona jako API.
źródło
Zasadniczo argv zawiera nazwę programu, dzięki czemu można pisać komunikaty o błędach, takie jak
prgm: file: No such file or directory
, które można zaimplementować za pomocą czegoś takiego:źródło
Innym przykładem zastosowania tego jest ten program, który zamienia się na ... sam, dopóki nie wpiszesz czegoś, co nie jest
y
.Oczywiście jest to wymyślony, choć interesujący przykład, ale myślę, że może mieć prawdziwe zastosowanie - na przykład samoregulujący plik binarny, który przepisuje własną przestrzeń pamięci przy użyciu nowej wersji siebie, którą pobrał lub zmienił.
Przykład:
Źródło i więcej informacji .
źródło
Ścieżka do programu jest
argv[0]
taka, aby program mógł pobierać pliki konfiguracyjne itp. Ze swojego katalogu instalacyjnego.Bez tego byłoby to niemożliwe
argv[0]
.źródło
(char *path_to_program, char **argv, int argc)
na przykład~/.<program>
,/etc/<program
,$XDG_CONFIG_HOME
) i albo przyjąć parametr zmienić go lub posiada opcję kompilacji, które piecze w stałym do binarnego.ccache zachowuje się w ten sposób, aby naśladować różne wywołania do plików binarnych kompilatora. ccache to pamięć podręczna kompilacji - chodzi o to, aby nigdy nie skompilować dwukrotnie tego samego kodu źródłowego, ale zamiast tego zwrócić kod obiektu z pamięci podręcznej, jeśli to możliwe.
Ze strony podręcznika ccache „istnieją dwa sposoby korzystania z ccache. Możesz albo poprzedzić polecenia kompilacji ccache, albo możesz pozwolić ccache maskować się jako kompilator, tworząc dowiązanie symboliczne (zwane kompilatorem) do ccache. Pierwsza metoda jest najwygodniejszy, jeśli chcesz wypróbować pamięć podręczną lub użyć jej w niektórych konkretnych projektach. Druga metoda jest najbardziej przydatna, gdy chcesz używać pamięci podręcznej do wszystkich swoich kompilacji. ”
Metoda symlinks polega na uruchomieniu następujących poleceń:
... którego efektem jest umożliwienie ccache'owi przechwycenia wszelkich poleceń, które w innym przypadku trafiłyby do kompilatorów, umożliwiając w ten sposób zwrócenie buforowanego pliku lub przekazanie polecenia do kompilatora.
źródło