exec()
기능과 그 제품군 은 무엇입니까 ? 이 기능은 왜 사용되며 어떻게 작동합니까?
누구든지 이러한 기능을 설명하십시오.
exec()
기능과 그 제품군 은 무엇입니까 ? 이 기능은 왜 사용되며 어떻게 작동합니까?
누구든지 이러한 기능을 설명하십시오.
답변:
간단히 말해서 UNIX에서는 프로세스와 프로그램의 개념이 있습니다. 프로세스는 프로그램이 실행되는 환경입니다.
UNIX "실행 모델"뒤에있는 간단한 아이디어는 수행 할 수있는 두 가지 작업이 있다는 것입니다.
첫 번째는 fork()
상태를 포함하여 현재 프로그램의 중복 (대부분)을 포함하는 새로운 프로세스를 생성하는 to 입니다. 두 프로세스 간에는 부모와 자식을 파악할 수있는 몇 가지 차이점이 있습니다.
두 번째는 ~로 exec()
, 현재 프로세스의 프로그램을 새로운 프로그램으로 대체합니다.
이 두 가지 간단한 작업을 통해 전체 UNIX 실행 모델을 구성 할 수 있습니다.
위에 더 자세한 정보를 추가하려면 :
fork()
및 사용exec()
새로운 프로세스를 시작하는 매우 간단한 방법을 제공한다는 점에서 UNIX 모범 사례입니다.
이 fork()
호출은 거의 모든면에서 동일한 현재 프로세스를 거의 복제합니다 (예를 들어 일부 구현에서는 리소스 제한을 통해 모든 것이 복사되는 것은 아니지만 가능한 한 가까운 복사본을 만드는 것입니다). 하나의 프로세스 호출 fork()
만 해당 호출에서 두 개의 프로세스가 반환됩니다. 이상하게 들리지만 정말 우아합니다.
새 프로세스 (하위라고 함)는 다른 프로세스 ID (PID)를 가져오고 이전 프로세스 (상위)의 PID를 상위 PID (PPID)로 갖습니다.
두 프로세스가 이제 정확히 동일한 코드를 실행하고 있기 때문에 어떤 것이 무엇인지 알 수 있어야합니다. 반환 코드 fork()
는이 정보 를 제공합니다. 자식은 0을 얻고 부모는 자식의 PID를 얻습니다 (fork()
실패하면 자식이 생성되고 부모가 오류 코드를받습니다).
이렇게하면 부모는 자식의 PID를 알고 통신하고, 죽이고, 기다릴 수 있습니다 (자식은 항상를 호출하여 부모 프로세스를 찾을 수 있음 getppid()
).
이 exec()
호출은 프로세스의 현재 전체 내용을 새 프로그램으로 대체합니다. 프로그램을 현재 프로세스 공간으로로드하고 진입 점에서 실행합니다.
그래서, fork()
그리고 exec()
종종 현재 프로세스의 자식으로 실행되는 새 프로그램을 얻기 위해 순서대로 사용됩니다. 쉘은 일반적으로 find
쉘 포크 와 같은 프로그램을 실행하려고 할 때마다이를 수행 합니다.find
프로그램을 메모리에 모든 명령 줄 인수, 표준 I / O 등을 설정합니다.
그러나 함께 사용할 필요는 없습니다. 예를 들어 프로그램에 부모 및 자식 코드가 모두 포함되어있는 경우 프로그램이 fork()
다음없이 호출하는 것은 완벽하게 허용됩니다 exec()
(사용자가 수행하는 작업에주의해야하며 각 구현에는 제한이있을 수 있음).
이것은 단순히 TCP 포트에서 수신 대기하고 부모가 수신 상태로 돌아가는 동안 특정 요청을 처리하기 위해 자신의 사본을 포크하는 데몬에 대해 상당히 많이 사용되었습니다. 이 경우 프로그램에는 상위 및 하위 코드 가 모두 포함 됩니다.
마찬가지로, 그들은이 완료 알고 프로그램은 필요하지 않는 다른 프로그램 실행하려면 fork()
, exec()
다음 wait()/waitpid()
아이에 대한합니다. 을 사용하여 자식을 현재 프로세스 공간에 직접로드 할 수 있습니다 exec()
.
일부 UNIX 구현에는 fork()
COW (copy-on-write)라고하는 것을 사용 하는 최적화 기능 이 있습니다. 이것은 fork()
프로그램이 해당 공간에서 무언가를 변경하려고 시도 할 때까지 프로세스 공간의 복사를 지연시키는 트릭 입니다. 이것은 전체 프로세스 공간을 복사 할 필요가 없다는 점에서 사용 fork()
하지 않고 사용하는 프로그램에 유용 exec()
합니다. Linux에서는 fork()
페이지 테이블과 새 작업 구조의 복사본 만 만들어 exec()
두 프로세스의 메모리를 "분리"하는 번거로운 작업을 수행합니다.
이 경우 exec
됩니다 다음 호출 fork
(이 대부분 일 것입니다), 그 프로세스 공간에 쓰기의 원인 및 수정이 허용되기 전에 다음, 자식 프로세스를 위해 복사됩니다.
Linux에는 또한 두 프로세스간에 vfork()
거의 모든 것을 공유하는 훨씬 더 최적화 된 . 그 때문에, 아이를 호출 할 때까지 어떤 아이가 할 수있는 일에 제한하고, 부모가 정지있다 exec()
거나 _exit()
.
두 프로세스가 동일한 스택을 공유하기 때문에 부모를 중지해야합니다 (그리고 자식은 현재 함수에서 반환 할 수 없습니다). 이것은 fork()
바로 뒤에 오는 클래식 사용 사례에 대해 약간 더 효율적입니다 exec()
.
전체 exec
호출 제품군 ( execl
, execle
등 execve
)이 있지만 exec
여기서 문맥 상 해당 호출 중 하나를 의미합니다.
다음 다이어그램 은 명령 으로 디렉토리를 나열하는 데 쉘이 사용되는 일반적인 fork/exec
작업을 보여줍니다 .bash
ls
+--------+
| pid=7 |
| ppid=4 |
| bash |
+--------+
|
| calls fork
V
+--------+ +--------+
| pid=7 | forks | pid=22 |
| ppid=4 | ----------> | ppid=7 |
| bash | | bash |
+--------+ +--------+
| |
| waits for pid 22 | calls exec to run ls
| V
| +--------+
| | pid=22 |
| | ppid=7 |
| | ls |
V +--------+
+--------+ |
| pid=7 | | exits
| ppid=4 | <---------------+
| bash |
+--------+
|
| continues
V
exec
현재 프로세스의 IO를 리디렉션하는 데 유틸리티가 사용되는 이유는 무엇 입니까? 인수없이 exec를 실행하는 "null"케이스가이 규칙에 어떻게 사용 되었습니까?
exec
수단 후, 서로이 과정에서 현재 프로그램 (쉘) 교체로 하지 캔으로 대체하는 다른 프로그램을 지정하기 만하면 의미 하지 않는다 그것을 대체합니다.
exec
없이 호출되는 퇴화 된 경우에이 동작이 남아있는 것을 볼 수 있습니다 . 실제로 취득하는 프로그램 - 그러나 약간은 새로운 프로그램에 대한 리디렉션의 원래 유용성 이후이 시나리오에서 이상한 exec
uted - 사라지고 현재 프로그램 리디렉션, 유용한 유물이 -되지 않는 exec
uted 또는 시작을 대신에.
exec () 계열의 함수는 다른 동작을합니다.
혼합 할 수 있으므로 다음이 있습니다.
이들 모두에 대해 초기 인수는 실행될 파일의 이름입니다.
자세한 내용은 exec (3) 매뉴얼 페이지를 참조하십시오 .
man 3 exec # if you are running a UNIX system
execve()
POSIX에 의해 정의 된 목록에서 누락 되었고 POSIX에 execvpe()
의해 정의되지 않은 을 추가 했습니다 (주로 역사적 선례의 이유로 인해 기능 집합을 완료합니다). 그렇지 않으면, 패밀리의 명명 규칙에 대한 유용한 설명 — paxdiablo 의 유용한 부속물 인 기능의 작동에 대해 자세히 설명 하는 답변 입니다.
execvpe()
(et al)에 대한 리눅스 man 페이지 가 나열하지 않는다는 것을 알았습니다 execve()
; 별도의 매뉴얼 페이지 (최소한 Ubuntu 16.04 LTS에 있음)가 있습니다. 차이점은 다른 exec()
제품군 기능은 섹션 3 (기능) execve()
에 나열되고 섹션 2 (시스템 호출)에 나열되어 있다는 점입니다. 기본적으로 패밀리의 다른 모든 기능은 execve()
.
exec
기능의 제품군은 프로세스가 실행 된 이전 프로그램을 대체하는 다른 프로그램을 실행합니다. 즉, 전화하면
execl("/bin/ls", "ls", NULL);
그런 다음 ls
프로그램은 프로세스 ID, 현재 작업 디렉토리 및 호출 한 프로세스의 사용자 / 그룹 (액세스 권한)으로 실행됩니다.execl
됩니다. 이후에는 원래 프로그램이 더 이상 실행되지 않습니다.
새 프로세스를 시작하기 위해 fork
시스템 호출이 사용됩니다. 원본을 바꾸지 않고 프로그램을 실행하려면 fork
, exec
.
exec 기능과 그 제품군은 무엇입니까?
exec
기능 군은 같은 파일을 실행하기위한 모든 함수 인 execl
, execlp
, execle
, execv
, 및 execvp
.They 대한 모든 프론트 엔드이다 execve
하고 호출하는 다른 방법을 제공한다.
이 기능이 사용되는 이유
Exec 함수는 파일 (프로그램)을 실행 (시작) 할 때 사용됩니다.
어떻게 작동합니까?
현재 프로세스 이미지를 시작한 이미지로 덮어 쓰는 방식으로 작동합니다. 현재 실행중인 프로세스 (exec 명령을 호출 한 프로세스)를 시작된 새 프로세스로 (종료하여) 대체합니다.
자세한 내용 은이 링크를 참조하십시오 .
exec
와 함께 사용되는 경우가 많으며 fork
, 이에 대해 물어 보셨으므로이를 염두에두고 논의하겠습니다.
exec
현재 프로세스를 다른 프로그램으로 바꿉니다. 닥터 후를 본 적이 있다면 이것은 그가 재생하는 것과 같습니다. 그의 오래된 몸은 새로운 몸으로 대체됩니다.
프로그램에서 이런 일이 발생하는 방식 은 프로그램 인수 (첫 번째 인수)로 exec
전달하는 파일이 exec
현재 사용자 (프로세스의 사용자 ID)에 의해 실행 가능한지 확인하기 위해 OS 커널이 확인하는 많은 리소스입니다. 만들기 exec
전화) 그리고 만약 그것이 가상 메모리로 새로운 프로세스 및 복사 현재 프로세스의 가상 메모리 매핑을 대체 있도록 argv
하고 envp
에 전달 된 데이터를 exec
새로운 가상 메모리 맵의 영역으로 전화를. 여기에서 몇 가지 다른 일이 발생할 수도 있지만 호출 한 프로그램에 대해 열려 있던 파일 exec
은 새 프로그램에 대해 여전히 열려 있고 동일한 프로세스 ID를 공유하지만 호출 한 프로그램 exec
은 중지됩니다 (exec가 실패하지 않는 한).
이렇게하는 이유 는 새 프로그램 실행을 이와 같이 두 단계로 분리 하여 두 단계 사이에 몇 가지 작업을 수행 할 수 있기 때문입니다. 가장 일반적인 방법은 새 프로그램에 특정 파일이 특정 파일 설명 자로 열려 있는지 확인하는 것입니다. (여기서 파일 디스크립터는와 같지 않지만 커널이 알고있는 값이라는 것을 기억하십시오 ). 이렇게하면 다음을 수행 할 수 있습니다. FILE *
int
int X = open("./output_file.txt", O_WRONLY);
pid_t fk = fork();
if (!fk) { /* in child */
dup2(X, 1); /* fd 1 is standard output,
so this makes standard out refer to the same file as X */
close(X);
/* I'm using execl here rather than exec because
it's easier to type the arguments. */
execl("/bin/echo", "/bin/echo", "hello world");
_exit(127); /* should not get here */
} else if (fk == -1) {
/* An error happened and you should do something about it. */
perror("fork"); /* print an error message */
}
close(X); /* The parent doesn't need this anymore */
이것은 다음을 실행합니다.
/bin/echo "hello world" > ./output_file.txt
명령 셸에서.
프로세스가 fork ()를 사용하면 자신의 복제본을 만들고이 복제본은 프로세스의 자식이됩니다. fork ()는 커널에서 두 번 반환하는 Linux에서 clone () 시스템 호출을 사용하여 구현됩니다.
예를 들어 이것을 이해합시다.
pid = fork();
// Both child and parent will now start execution from here.
if(pid < 0) {
//child was not created successfully
return 1;
}
else if(pid == 0) {
// This is the child process
// Child process code goes here
}
else {
// Parent process code goes here
}
printf("This is code common to parent and child");
이 예제에서는 자식 프로세스 내에서 exec ()가 사용되지 않는다고 가정했습니다.
그러나 부모와 자식은 PCB (프로세스 제어 블록) 속성 중 일부가 다릅니다. 이것들은:
그러나 어린이 기억은 어떻습니까? 자녀를위한 새 주소 공간이 생성됩니까?
아니오의 답변. fork () 다음에 부모와 자식 모두 부모의 메모리 주소 공간을 공유합니다. Linux에서 이러한 주소 공간은 여러 페이지로 나뉩니다. 자식이 부모 메모리 페이지 중 하나에 쓸 때만 해당 페이지의 복제본이 자식에 대해 생성됩니다. 이것은 쓰기시 복사 (하위가 쓸 때만 상위 페이지 복사)라고도합니다.
예를 들어 copy on write를 이해합시다.
int x = 2;
pid = fork();
if(pid == 0) {
x = 10;
// child is changing the value of x or writing to a page
// One of the parent stack page will contain this local variable. That page will be duplicated for child and it will store the value 10 in x in duplicated page.
}
else {
x = 4;
}
하지만 Copy on Write가 필요한 이유는 무엇입니까?
일반적인 프로세스 생성은 fork ()-exec () 조합을 통해 이루어집니다. 먼저 exec ()가 무엇을하는지 이해합시다.
Exec () 함수 그룹은 자식의 주소 공간을 새 프로그램으로 대체합니다. 자식 내에서 exec ()가 호출되면 자식에 대해 부모의 주소 공간과 완전히 다른 별도의 주소 공간이 생성됩니다.
fork ()와 관련된 쓰기 메커니즘이 없으면 중복 페이지가 하위에 대해 생성되고 모든 데이터가 하위 페이지에 복사됩니다. 새 메모리를 할당하고 데이터를 복사하는 것은 매우 비용이 많이 드는 프로세스입니다 (프로세서의 시간과 기타 시스템 리소스가 필요함). 또한 대부분의 경우 자식이 exec ()를 호출하고 자식의 메모리를 새 프로그램으로 대체한다는 것도 알고 있습니다. 그래서 우리가 한 첫 번째 사본은 기록 중 사본이 없으면 낭비되었을 것입니다.
pid = fork();
if(pid == 0) {
execlp("/bin/ls","ls",NULL);
printf("will this line be printed"); // Think about it
// A new memory space will be created for the child and that memory will contain the "/bin/ls" program(text section), it's stack, data section and heap section
else {
wait(NULL);
// parent is waiting for the child. Once child terminates, parent will get its exit status and can then continue
}
return 1; // Both child and parent will exit with status code 1.
부모가 자식 프로세스를 기다리는 이유는 무엇입니까?
exec () 시스템 호출이 필요한 이유는 무엇입니까?
fork ()와 함께 exec ()를 사용할 필요는 없습니다. 자식이 실행할 코드가 부모와 관련된 프로그램 내에 있으면 exec ()가 필요하지 않습니다.
그러나 자녀가 여러 프로그램을 실행해야하는 경우를 생각해보십시오. 쉘 프로그램의 예를 들어 보겠습니다. find, mv, cp, date 등과 같은 여러 명령을 지원합니다. 이러한 명령과 관련된 프로그램 코드를 하나의 프로그램에 포함하거나 필요할 때 자식이 이러한 프로그램을 메모리에로드하도록하는 것이 옳습니까?
그것은 모두 사용 사례에 달려 있습니다. 클라이언트에 2 ^ x를 반환하는 입력 x를 제공하는 웹 서버가 있습니다. 각 요청에 대해 웹 서버는 새 자식을 만들고 계산하도록 요청합니다. 이것을 계산하고 exec ()를 사용하는 별도의 프로그램을 작성 하시겠습니까? 아니면 부모 프로그램 안에 계산 코드를 작성 하시겠습니까?
일반적으로 프로세스 생성에는 fork (), exec (), wait () 및 exit () 호출의 조합이 포함됩니다.
exec(3,3p)
기능을 대체 서로 현재의 프로세스를. 즉, 현재 프로세스 가 중지 되고 대신 다른 프로세스 가 실행되어 원래 프로그램이 보유한 일부 리소스를 인수합니다.