exec 함수에서 파일 이름을 두 번 전달해야 하는 이유는 무엇입니까?

exec 함수에서 파일 이름을 두 번 전달해야 하는 이유는 무엇입니까?

나는 읽었다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 xzxz를 검사하여 호출 방법을 확인하여 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]로 설정됩니다 ../foodir/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이와 같은 상황을 위한 것입니다.

관련 정보