Yürütme işlevlerinde dosya adını neden iki kez iletmemiz gerekiyor?


12

Okuduğum Gelişmiş UNIX Ortamında Programlama Stevens, 8 ile inci bölüm. Ben exec işlevlerinin altı okudum ve anlıyorum.

Fark ettiğim bir şey, tüm exec işlevlerinde:

  • ilk argüman dosya adı / yol adıdır (exec fonksiyonuna bağlıdır).
  • ikinci argüman içeri girdiğimiz argv [0] main(), yani dosya adının kendisi.

Yani burada dosya ismini fonksiyonda iki kez geçmemiz gerekiyor.

Bunun herhangi bir nedeni var mı (dosya adını ilk argümandaki yol adından alamıyoruz gibi)?

Yanıtlar:


15

Yani burada dosya ismini fonksiyonda iki kez geçmemiz gerekiyor.

Bunlardan birininargv[0] değer olarak kullanıldığını gözlemleyerek fark ettiğiniz gibi değiller . Bunun çalıştırılabilir dosyanın taban adıyla aynı olması gerekmez; birçok / çoğu şey onu görmezden gelir ve oraya ne istersen koyabilirsin.

Birincisi, açık bir zorunluluk olan yürütülebilir dosyaya giden gerçek yoldur. İkincisi, görünüşe göre onu çağırmak için kullanılan ad olarak geçirilir, ancak, örneğin:

execl("/bin/ls", "banana", "-l", NULL);

İyi çalışacaktır /bin/ls, doğru yol olduğunu varsayalım .

Ancak bazı uygulamalar yararlanır argv[0]. Genellikle bunların içinde bir veya daha fazla sembolik bağlantı vardır $PATH; bu sıkıştırma yardımcı programlarında yaygındır (bazen bunun yerine kabuk sarmalayıcıları kullanırlar). Eğer varsa xz, yüklü stat $(which xzcat)gösterileri bunun için bir bağlantı xzve man xzcataynı gibidir man xz"xzcat xz --decompress --stdout eşdeğerdir" açıklıyor. Xz'nin nasıl çağrıldığını söyleyebilmesinin yolu argv[0]şu eşdeğerdir:

execl("/bin/xz", "xzcat", "somefile.xz", NULL);
execl("/bin/xz", "xz", "--decompress", "--stdout", "somefile.xz", NULL);

5
Ah, bu nasıl busyboxdediğinize bağlı olarak nasıl olmasını istediğinizi açıklayabilir mi?
terdon

4
@terdon Meşgul kutusu için tek ikili tam olarak bu kadar çok farklı komutu karşılar.
mah

7
Bu /bin/ls, meşgul kutusu olsaydı , nasıl çalıştırılacağını bilmeyeceği anlamına gelir banana!
Riking

6

Dosya adını iki kez iletmeniz gerekmez.

Birincisi, gerçekte yürütülen dosyadır.

İkinci argüman, argv[0]sürecin ne olması gerektiği , yani sürecin adı olarak ne görmesi gerektiğidir. Kabuktan kaçarsanız ls, ilk argüman /bin/lsikincisidir ls.

Belirli bir dosyayı yürütebilir ve ikinci argüman aracılığıyla başka bir dosya olarak adlandırabilirsiniz; program adını kontrol edebilir ve isme göre farklı davranabilir. Bu, sabit bağlantılar (veya sembolik bağlantılar) yoluyla da yapılabilir, ancak bu şekilde daha fazla esneklik sağlar.


Aslında argv[0], bağlantı adı olarak ayarlandığından bağlantılar aynı yöntemdir .
goldilocks

Son paragrafta, "Belirli bir dosyayı yürütebilir ve ikinci argüman aracılığıyla başka bir şey olarak adlandırabilirsiniz; program adını kontrol edebilir ve isme göre" farklı "davranabilir". Lütfen biraz ayrıntı verebilir misiniz veya bana okumalar yapabilir misiniz, bu ortam için yeni bir şeyim.
munjal007

Goldilocks'ın cevabının son kısmı bunu açıklıyor.
wurtel

1

Paket servisi argv[0]olan şey (dahil NULL) herhangi bir şey için ayarlanabilir olduğunu . Geleneksel olarak , argv[0]devam eder (kabuk işlemi ile yürütülebilir olarak başlatıldı yolu ayarlanır execve()).

Eğer ./foove dir/baraynı yürütülebilir (sabit ya da sembolik), iki farklı bağlantılar, daha sonra koyacaktır iki yol kullanılarak kabuğundan program başlangıç argv[0]için ./foove dir/barsırasıyla.

Aslında argv[0]olabilir NULLçoğu zaman göz ardı edilmektedir. Aşağıdaki kod NULL argv[0], örneğin kilitlenebilir (glibc bunun yerine <boş> gibi bir şey yazdırsa da argv[0]):

if (argc != 3) {
    fprintf(stderr, "%s: expected 2 arguments\n", argv[0]);
    exit(EXIT_FAILURE);
}

Linux'ta bir alternatif /proc/self/exebu gibi durumlar için kullanmaktır .


argv [0] 'ı hem ./foo hem de dir / bar olarak nasıl ayarlayabilirsiniz
munjal007

@ munjal007 Belirsiz olduğum için üzgünüm. Programı iki kez çalıştırmak istedim: bir kez ./foove bir kez dir/bar. argv[0]bu iki durum için farklı olacaktır (her durumda kullandığınız yolla aynı olacaktır).
Ulfalizer

@ munjal007 Elbette kabuğundan çalıştırdığınız varsayılıyor. Mesele şu ki , programı kendiniz argv[0]yaptığınızda herhangi bir şeye ayarlayabiliyorsunuz exec*(). Bu argv[0], programı başlatmak için kullanılan yola ayarlamak için bir kabuk kuralıdır (ve exec*()bir program yaptığınızda aynı işlemi yapmak akıllıca olacaktır , çünkü birçok program yolu izlemesini argv[0]ve beklemesini beklemektedir).
Ulfalizer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.