나는 읽었다UNIX 환경의 고급 프로그래밍저자: Stevens, 8 장 . 나는 6개의 exec 함수를 모두 읽고 이해합니다.
내가 주목한 한 가지는 모든 exec 함수에서 다음과 같다는 것입니다.
- 첫 번째 매개변수는 파일 이름/경로 이름입니다(exec 함수에 따라 다름).
- 두 번째 매개변수는
main()
파일 이름 자체인 argv[0]입니다.
따라서 여기서는 함수에 파일 이름을 두 번 전달해야 합니다.
어떤 이유가 있나요(첫 번째 매개변수의 경로 이름에서 파일 이름을 가져올 수 없는 것과 같은)?
답변1
따라서 여기서는 함수에 파일 이름을 두 번 전달해야 합니다.
그것들은 당신이 관찰함으로써 알아차린 것과 정확히 일치하지 않습니다하나그 중 하나가 값으로 사용됩니다 argv[0]
. 이것은 실행 파일의 기본 이름과 동일할 필요는 없습니다. 많은/대부분의 것들이 이를 무시하므로 거기에 원하는 것을 넣을 수 있습니다.
첫 번째는 분명히 필요한 실행 파일의 실제 경로입니다. 두 번째는 표면적으로는 호출하는 데 사용된 이름으로 프로세스에 전달되지만 예를 들면 다음과 같습니다.
execl("/bin/ls", "banana", "-l", NULL);
/bin/ls
올바른 경로라고 가정하면 제대로 작동합니다.
그러나 일부 응용 프로그램은 를 사용합니다 argv[0]
. 일반적으로 이러한 응용 프로그램에는 $PATH
; 이는 압축 유틸리티에서 일반적입니다(대신 셸 래퍼를 사용하는 경우도 있음). xz
설치 한 경우 stat $(which xzcat)
해당 링크가 표시되며 xz
"xzcat은 xz --decompress --stdout과 동일합니다"라고 설명하는 것과 동일합니다 man xzcat
. man xz
xz를 검사하여 호출 방법을 확인하여 argv[0]
동일하게 만들 수 있습니다.
execl("/bin/xz", "xzcat", "somefile.xz", NULL);
execl("/bin/xz", "xz", "--decompress", "--stdout", "somefile.xz", NULL);
답변2
파일 이름을 두 번 전달할 필요는 없습니다.
첫 번째는 실행되는 실제 파일입니다.
두 번째 매개변수는 프로세스의 이름 argv[0]
, 즉 프로세스의 이름입니다. 예를 들어, ls
셸에서 실행하는 경우 첫 번째 인수는 /bin/ls
이고 두 번째 인수는 입니다 ls
.
두 번째 매개변수로 파일을 실행하고 다른 이름으로 호출할 수 있습니다. 프로그램은 파일 이름을 확인하고 이름에 따라 다르게 동작할 수 있습니다. 이는 하드 링크(또는 기호 링크)를 통해서도 수행할 수 있지만 이 방법을 사용하면 더 많은 유연성이 제공됩니다.
답변3
중요한 점은 argv[0]
모든 값(포함)으로 설정할 수 있다는 것입니다 NULL
.관례에 따르면, argv[0]
실행 파일이 시작될 때(셸 프로세스에 의해 실행될 때 execve()
) 실행 파일의 경로로 설정됩니다.
./foo
및 가 동일한 실행 파일에 대한 두 개의 다른 링크(하드 또는 기호) 인 경우 dir/bar
이 두 경로를 사용하여 셸에서 프로그램을 시작하면 각각 및 argv[0]
로 설정됩니다 ../foo
dir/bar
사실 이 점을 간과하는 argv[0]
경우가 많습니다 NULL
. 예를 들어, 다음 코드는 충돌이 발생할 수 있습니다 NULL
argv[0]
(glibc는 다음과 같은 내용을 인쇄하지만).<비어있음>그리고 argv[0]
):
if (argc != 3) {
fprintf(stderr, "%s: expected 2 arguments\n", argv[0]);
exit(EXIT_FAILURE);
}
Linux의 또 다른 옵션은 /proc/self/exe
이와 같은 상황을 위한 것입니다.