programing

Linux에서 "system"과 "exec"의 차이점은 무엇입니까?

luckcodes 2022. 7. 19. 22:14

Linux에서 "system"과 "exec"의 차이점은 무엇입니까?

와의 차이는 무엇입니까?system그리고.exec가족 명령어?특히 그 중 어떤 것이 아동 노동 과정을 만들어 내는지 알고 싶습니다.

system()로의 호출.sh와일드카드 확장 등을 얻을 수 있도록 커맨드 라인을 처리합니다. exec()현재 프로세스 이미지를 새로운 프로세스 이미지로 교체합니다.

와 함께system()프로그램이 계속 실행되고 호출한 외부 명령에 대한 상태가 표시됩니다.와 함께exec()프로세스가 삭제됩니다.

일반적으로, 제 생각엔system()더 높은 수준의 인터페이스로 사용됩니다.일부 조합을 사용하여 직접 기능을 복제할 수 있습니다.fork(),exec(),그리고.wait().

마지막 질문에 답하기 위해system()자프로세스가생성됩니다.exec()가족은 그렇지 않다.를 사용해야 합니다.fork()그럴 수 있어요.

exec 함수는 성공 시 현재 실행 중인 프로세스이미지를 바꿉니다(자식이 생성되지 않은 경우).fork()system() 함수는 자 프로세스를 분기하여 지정된 명령어 실행이 완료되거나 오류가 발생하면 반환됩니다.

system()은 시스템 기본 명령어셸을 호출합니다.이 셸은 인수로 전달된 명령어 문자열을 실행합니다.이 셸은 명령어와 시스템에 따라 달라지는 추가 프로세스를 작성하거나 작성하지 않을 수 있습니다.어느 쪽이든 적어도 명령 셸 프로세스가 생성됩니다.

system()에서는 임의의 명령어를 호출할 수 있지만 exec()에서는 실행 파일만 호출할 수 있습니다.셸 스크립트와 배치 파일은 명령 셸에서 실행해야 합니다.

기본적으로 그것들은 완전히 다른 목적으로 사용된다.게다가 exec()은 호출 프로세스를 대체하고 반환되지 않습니다.보다 유용한 비교는 system()과 span()을 비교하는 것입니다.시스템은 호출이 더 간단하지만 명령어셸이 호출되었는지 여부를 나타내는 값을 반환하고 명령어 자체의 성공 여부는 알 수 없습니다.spoen()을 사용하면 프로세스의 종료 코드를 얻을 수 있습니다.규칙상 0 이외의 코드는 에러 상태를 나타내기 위해 사용됩니다.exec() spoen()처럼 셸 스크립트나 삽입 명령어가 아닌 실행 파일을 호출해야 합니다.

Child_status가 int(int에 대한 포인터 없음)여야 하며 참조에 의해 대기 함수를 전달해야 한다는 점을 제외하면 JonSpencer의 답변은 정상입니다.

따라서 코드는 주로 동일하며, 몇 가지 사항을 변경할 뿐입니다.

#include <unistd.h>
#include <sys/wait.h>
#define NUMARGS 2

int main (int argc, char *argv[])
{
  pid_t child_pid, wait_pid;
  int child_status;
  char * exec_path = "/path/to/executable";
  char * child_args[NUMARGS] = {0,0};

  child_pid = fork();
  if (0 == child_pid)
  { // In child process
     ...
     int child_ret_code = execv(exec_path, child_args);  //or whichever flavor of exec() that floats your boat
     ... // if child_ret_code = -1, process execv() error return
  }
  else if (-1 == child_pid)
  {
     ... //process error return from fork
  }
  else if (0 < child_pid)
  {  // Parent process
     wait_pid = wait(&child_status);
     if (-1 == wait_pid)
     {
       ... //Process error return from wait()
     }
     else
     {  //  Good fork/exec/wait
        if (WIFEXITED(child_status))  // Child exited normally and hopefully returned exit code
        {
           int child_ret_code = WEXITSTATUS(child_status);
           ...  // Continue on as you would after call to system(3)
                //   except now you have the return code you needed
        }
     }
  }
}

(John의 투고에 코멘트를 달 만한 평판이 아직 부족하기 때문에 편집했습니다.편집하지 말고 질문에 답해 달라고 거절한 사람도 있지만, 이 경우 완전한 복사/붙여넣기/수정보다는 기존의 코드를 수정하는 것이 훨씬 간단하고 실용적이며 명확하다고 생각합니다.)어쨌든, Jon Spencer의 답변에 감사드리며, 저에게 정말 도움이 되었습니다!

system()는 생성된 자 프로세스에서 제공된 명령을 실행합니다. exec()는 현재 프로세스를 지정한 새 실행 파일의 호출로 대체합니다.다음을 사용하여 하위 프로세스를 생성하는 경우exec, 당신은 해야 합니다.fork()프로세스를 미리 준비합니다.

프로세스를 작성하려면:

  • fork(2), 커널에 직접 시스템콜을 송신

프로그램을 실행하려면 현재 이미지를 바꿉니다.

  • execve(2)커널에 직접 시스템콜(보통 그냥 콜)exec

하위 프로세스가 완료될 때까지 대기하려면:

  • wait(2), 커널에 직접 시스템콜을 송신

하위 프로세스의 셸에서 프로그램을 실행하고 완료될 때까지 기다리려면:

  • system(3), 라이브러리 기능

위의 모든 내용에 대한 man 페이지를 가져오려면:

   $ man 2 fork execve wait
   $ man 3 system

사이에는 몇 가지 중요한 차이가 있다exec(2)그리고.system(3)명심해야 할 사항입니다. system()는 발신자에게 반환됩니다만,exec()는 기존 코드를 새 이미지로 바꿉니다.이것은 위에서 설명한 바와 같습니다.

다만, 프로시저를 실행하고 나서, 호출된 프로시저로부터 리턴 코드를 수신해 기존의 코드로 되돌리는 경우는, 그다지 미묘한 차이가 없습니다. system()는 리턴 코드를 제공하지만 리턴 코드를 사용할 수 있는 것은 오류 상태의 검출뿐이며 리턴 코드 회복에는 사용할 수 없습니다.

시스템 콜의 적절한 시퀀스는 다음과 같습니다.

#include <unistd.h>
#include <sys/wait.h>
#define NUMARGS 2

int main (int argc, char *argv[])
{
  pid_t child_pid, wait_pid;
  int * child_status;
  char * exec_path = "/path/to/executable";
  char * child_args[NUMARGS] = {0,0};

  child_pid = fork();
  if (0 == child_pid)
  { // In child process
     ...
     int child_ret_code = execv(exec_path, child_args);  //or whichever flavor of exec() that floats your boat
     ... // if child_ret_code = -1, process execv() error return
  }
  else if (-1 == child_pid)
  {
     ... //process error return from fork
  }
  else if (0 < child_pid)
  {  // Parent process
     wait_pid = wait(child_status);
     if (-1 == wait_pid)
     {
       ... //Process error return from wait()
     }
     else
     {  //  Good fork/exec/wait
        if (WIFEXITED(child_status))  // Child exited normally and hopefully returned exit code
        {
           int child_ret_code = WEXITSTATUS(child_status);
           ...  // Continue on as you would after call to system(3)
                //   except now you have the return code you needed
        }
     }
  }
}

이 시퀀스에는 관련된 man 페이지를 주의 깊게 읽으면 알 수 있는 다른 미묘한 점이 있지만, 신호가 없거나 여러 개의 하위 프로세스 등이 없는 경우 이 코드는 정상적으로 작동합니다.또한 인라인 선언은 변수의 범위를 제한할 수 있지만 이 코드를 템플릿으로 사용할 수 있도록 하기 위해 포함되어 있습니다(다른 코딩 스타일:- 사용 가능).


int system(const char *cmdstring);

예:system("date > file");


일반적으로 시스템은 fork, exec waitpid에 의해 구현되며 반환값에는 3가지 유형이 있습니다.

  • 포크가 실패하거나 waitpid가 EINTR 이외의 오류를 반환할 경우 시스템은 오류를 나타내기 위해 errno를 설정하고 -1을 반환합니다.
  • exec이 실패하여 셸을 실행할 수 없는 경우 반환값은 셸이 exit(127)을 실행한 것과 같습니다.
  • 그렇지 않으면 fork, exec 및 waitpid의 3가지 기능이 모두 성공하며 시스템에서 반환되는 값은 waitpid에 지정된 형식으로 셸의 종료 상태가 됩니다.

포크 함수는 exec 함수 중 하나를 호출하여 다른 프로그램을 실행하는 새로운 프로세스(자녀)를 만드는 것입니다.프로세스가 exec 함수 중 하나를 호출하면 해당 프로세스는 새 프로그램으로 완전히 대체되고 새 프로그램은 주요 함수에서 실행을 시작합니다.새로운 프로세스가 생성되지 않기 때문에 프로세스 ID는 exec 전체에서 변경되지 않습니다.exec은 현재 프로세스(텍스트, 데이터, 힙 및 스택세그먼트)를 디스크에서 완전히 새로운 프로그램으로 대체할 뿐입니다.

6개의 다른 exec 기능이 있습니다.


int execl(const char *pathname, const char *arg0, ... /* (char *)0 */ );

int execv(const char *pathname, char *const argv []);

int execle(const char *pathname, const char *arg0, .../* (char *)0, char *const envp[] */ );

int execve(const char *pathname, char *const argv[], char *const envp []);

int execlp(const char *filename, const char *arg0,... /* (char *)0 */ );

int execvp(const char *filename, char *const argv []);

exec()은 현재 실행 중인 프로세스를 수행 중인 함수의 프로세스 이미지로 대체합니다.이를 사용하여 실행 파일만 호출할 수 있습니다.

system()은 새로운 프로세스를 암묵적으로 분기하여 요청을 처리하고 처음에 분기한 자식 프로세스를 통해 얻은 값을 반환합니다.시스템의 기본 셸을 사용하여 작업을 수행합니다.

System()은 하위 프로세스를 생성하고 다른 하위 셸을 호출하지만 exec()은 하위 프로세스를 생성하지 않습니다.예를 제시하면 차이가 해소됩니다.

어떤 코드...

exec4ls - l')

echo "1 2 3" // 이것은 bash에서는 실행되지 않습니다(exec 명령어는 같은 셸을 사용합니다).

어떤 코드...

system (ls - l) echo "1 2 3" // 부모 PID와 다르기 때문에 시스템자녀프로세스를 종료한 후에 실행됩니다.

system()은 셸을 사용하여 원하는 프로그램 또는 삽입 명령을 호출합니다.이것은 셸이 프로그램이 시작되기 전에 시작되므로 비효율적인 방법입니다.

시스템 콜의 exec 패밀리의 경우 완전히 새로운 이미지가 작성됩니다.즉, 현재 프로세스를 경로 또는 파일 또는 언급하고 있는 인수에 의해 지정된 새로운 프로세스로 대체합니다.

주의할 점은 시스템콜의 exec 패밀리를 사용하면 새로운 프로그램이 시작된 후에는 원래 프로그램이 실행되지 않는다는 것입니다.

일반적으로 "시스템"은 매우 비효율적이며 작은 코드가 없는 한 사용하지 마십시오.프로세스에서 여러 프로그램을 실행해야 하는 경우 fork&exec을 사용하는 것이 좋습니다.단, 더 복잡해집니다.다음은 이들 간의 차이점 목록입니다.

1- "system" 명령은 프로그램을 실행하기 위한 셸 복사본을 생성합니다.시스템을 호출할 때마다 셸 복사본을 만듭니다.따라서 프로세스 내에서 실행할 프로그램이 많을 때는 사용하지 마십시오.

2-구체적으로 "mv"나 "mkdir"와 같은 시스템 함수를 실행하는 경우 "system("rm ..")" 또는 system("mkdir .."")을 통해 실행하는 대신 mkdir(), unlink() 또는 remove() 등의 루틴을 사용하는 것이 좋습니다.

3- 시스템이 셸을 호출하여 원하는 프로그램을 실행하기 때문에 사용자 권한에 문제가 있을 수 있습니다.예를 들어, system 명령어를 사용하여 실행하려는 프로그램이 아닌 다른 사용자가 코드를 해제하고 다른 프로그램을 실행할 수 있습니다.

상세한 것에 대하여는, 데이비드 커리의 「UNIX 시스템 프로그래밍」의 제11 장을 참조해 주세요.

언급URL : https://stackoverflow.com/questions/1697440/difference-between-system-and-exec-in-linux