왜 exec 함수에서 파일 이름을 두 번 전달해야합니까?


12

본인은 고급은 UNIX 환경에서 프로그래밍 스티븐스, 8 장. 나는 6 가지 exec 함수를 읽고 이해합니다.

내가 주목하는 것은 모든 exec 함수에서 :

  • 첫 번째 인수는 파일 이름 / 경로 이름입니다 (exec 함수에 따라 다름).
  • 두 번째 인수는 argv [0]이며 main()파일 이름 자체입니다.

따라서 함수에서 파일 이름을 두 번 전달해야합니다.

그 이유가 있습니까? (첫 번째 인수에서 경로 이름에서 파일 이름을 가져올 수없는 것처럼)?

답변:


15

따라서 함수에서 파일 이름을 두 번 전달해야합니다.

그것들은 그중 하나argv[0]값으로 사용 된다는 것을 관찰함으로써 당신이 알고있는 것과 완전히 다릅니다 . 실행 파일의 기본 이름과 같을 필요는 없습니다. 많은 / 대부분의 것들이 그것을 무시하고 거기에 원하는 것을 넣을 수 있습니다.

첫 번째는 실행 파일의 실제 경로이며, 여기에는 분명한 필요성이 있습니다. 두 번째는 호출하는 데 사용되는 이름으로 표면에 프로세스에 전달되지만 다음과 같습니다.

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

/bin/ls올바른 경로라고 가정 하면 잘 작동합니다 .

그러나 일부 응용 프로그램은을 사용 argv[0]합니다. 보통 이것들은 하나 이상의 심볼릭 링크를 가지고 있습니다 $PATH. 이것은 압축 유틸리티에서 일반적입니다 (때로는 쉘 래퍼를 대신 사용함). 이 경우 xz, 설치 stat $(which xzcat)프로그램을이에 대한 링크입니다 xz, 그리고 man xzcat동일 같다 man xz"xzcat는 XZ --decompress --stdout에 해당"에 대해 설명한다. xz가 어떻게 호출되었는지 알 수있는 방법은 다음을 확인 argv[0]하는 것입니다.

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

5
아, 그래서 이것은 busybox당신이 그것을 올바르게 부르는 방법에 따라 원하는 것이 될 수있는 방법을 설명 할 것입니까?
terdon

4
@terdon은 busybox의 단일 바이너리가 많은 다른 명령을 만족시키는 방법입니다.
mah mar

7
그것은 /bin/lsbusybox라면 실행 방법을 모른다 는 것을 의미합니다 banana!
Riking

6

파일 이름을 두 번 전달할 필요가 없습니다.

첫 번째는 실제로 실행되는 파일입니다.

두 번째 논점은 argv[0]프로세스가되어야하는 것, 즉 프로세스가 그 이름으로보아야하는 것입니다. 예 ls를 들어 쉘에서 실행 하면 첫 번째 인수는 /bin/ls이고 두 번째 인수는 ls입니다.

특정 파일을 실행하고 두 번째 인수를 통해 다른 파일을 호출 할 수 있습니다. 프로그램은 이름을 확인하고 이름에 따라 다르게 동작 할 수 있습니다. 하드 링크 (또는 심볼릭 링크)를 통해이 작업을 수행 할 수도 있지만이 방법으로 유연성을 높일 수 있습니다.


실제로 링크는 argv[0]링크 이름으로 설정되므로 동일한 방법 입니다.
goldilocks

마지막 단락에서 "두 번째 인수를 통해 특정 파일을 실행하고 다른 파일을 호출 할 수 있습니다. 프로그램은 파일 이름을 확인하고 이름에 따라 '다른 방식으로'동작 할 수 있습니다." 좀 더 자세히 설명해 주시거나이 환경에 익숙하지 않습니까?
munjal007

goldilocks의 답변의 마지막 부분이 이것을 설명합니다.
wurtel

1

테이크 아웃은를 argv[0]포함하여 무엇이든 설정할 수 있습니다 NULL. 관례argv[0]따라 실행 파일이 시작된 경로로 설정됩니다 (쉘 프로세스가 수행 할 때 execve()).

경우 ./foodir/bar같은 실행 파일 (하드 또는 심볼) 개의 상이한 링크는, 다음 설정 될 두 개의 경로를 이용하여 쉘에서 프로그램을 시작 argv[0]으로 ./foo하고 dir/bar, 각각.

argv[0]할 수있는 사실 NULL은 종종 간과됩니다. 다음 코드는 NULL argv[0]예를 들어 충돌 할 수 있습니다 (glibc는 대신 <null> 과 같은 것을 인쇄 합니다 argv[0]).

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

Linux의 대안 /proc/self/exe은 이러한 경우 에 사용하는 것 입니다.


argv [0]을 ./foo와 dir / bar 둘 다로 설정하는 방법
munjal007

@ munjal007 불분명해서 죄송합니다. 나는 프로그램을 두 번 실행하는 것을 의미 ./foo했다 dir/bar. argv[0]이 두 경우에 따라 다릅니다 (각 경우 사용한 경로와 동일).
Ulfalizer

@ munjal007 물론 쉘에서 실행한다고 가정합니다. 요점은 프로그램을 스스로 argv[0]할 때 무엇이든 설정할 수 있다는 exec*()것입니다. argv[0]프로그램을 시작하는 데 사용 된 경로 로 설정 하는 것은 셸의 규칙입니다. exec*()많은 프로그램 argv[0]이 경로를 검사 하고 유지 하기 를 기대 하기 때문에 프로그램을 실행할 때도 똑같이하는 것이 좋습니다 .
Ulfalizer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.