fork()는 어떻게 0을 반환할 시기를 알 수 있습니까?
다음 예를 들어 보겠습니다.
int main(void)
{
pid_t pid;
pid = fork();
if (pid == 0)
ChildProcess();
else
ParentProcess();
}
틀렸다면 정정해 주세요.fork()가 실행되면 자녀 프로세스가 생성됩니다.이 answer fork()를 사용하면 두 번 반환됩니다.이것은 부모 프로세스용과 자녀 프로세스용입니다.
즉, 포크 콜이 종료된 후가 아니라 포크 콜 중에 두 개의 개별 프로세스가 존재하게 됩니다.
자프로세스의 경우 0을 반환하는 방법과 부모프로세스의 경우 올바른 PID를 반환하는 방법을 이해할 수 없습니다.
여기가 정말 혼란스러운 곳이야이 답변은 fork()가 프로세스의 컨텍스트 정보를 복사하고 반환값을 수동으로0 으로 설정하는 것으로 동작하고 있음을 나타내고 있습니다.
먼저, 어떤 함수로의 복귀는 단일 레지스터에 저장된다는 말이 맞습니까?단일 프로세서 환경에서는 프로세스가 1개의 값만 반환하는 서브루틴을 1개만 호출할 수 있습니다(여기서 틀리면 정정해 주세요).
예를 들어 루틴 내의 함수 foo()를 호출하면 함수가 값을 반환하고 해당 값이 레지스터에 저장됩니다.예를 들어 BAR. 함수는 값을 반환할 때마다 특정 프로세서 레지스터를 사용합니다.프로세스 블록의 반환값을 수동으로 변경할 수 있으면 함수로 반환되는 값을 변경할 수 있는 거죠?
그러면 fork()가 그렇게 작동한다고 생각하는 것이 맞습니까?
동작방법은 거의 관계가 없습니다.특정 레벨(UNIX API에 대한 코딩)에서 작업하는 개발자로서 동작하는 것만 알면 됩니다.
그렇지만, 호기심이나 어느 정도 깊이 있는 이해의 필요성이 일반적으로 가지는 좋은 특성임을 인식하는 것은, 이것을 할 수 있는 많은 방법이 있습니다.
우선 함수가 1개의 값만 반환할 수 있다는 주장은 어디까지나 맞지만 프로세스가 분할된 후 실제로는 각 프로세스에서1개씩2개의 함수 인스턴스가 실행되고 있음을 기억해야 합니다.이들은 대부분 서로 독립적이며 서로 다른 코드 경로를 따를 수 있습니다.다음 그림은 이를 이해하는 데 도움이 될 수 있습니다.
Process 314159 | Process 271828
-------------- | --------------
runs for a bit |
calls fork |
| comes into existence
returns 271828 | returns 0
바라건대, 여기서 볼 수 있듯이fork
는 (다른 C 함수와 마찬가지로)1개의 값만 반환할 수 있지만 실제로는 여러 인스턴스가 실행 중이기 때문에 매뉴얼에서는 여러 값을 반환하는 것으로 알려져 있습니다.
이게 어떻게 작동될지에 대한 한 가지 가능성이 있습니다.
?fork()
함수는 실행을 시작하고 현재 프로세스 ID(PID)를 저장합니다.
그 후, PID가 보존되어 있는 것과 같은 경우는, 그 부모입니다.는 부모입니다.그렇지 않으면 아이일 거야의사 코드는 다음과 같습니다.
def fork():
saved_pid = getpid()
# Magic here, returns PID of other process or -1 on failure.
other_pid = split_proc_into_two();
if other_pid == -1: # fork failed -> return -1
return -1
if saved_pid == getpid(): # pid same, parent -> return child PID
return other_pid
return 0 # pid changed, child, return zero
이 ''에는split_proc_into_two()
전화하면 절대 그런(a) 식으로 안 될 거예요단지, 그 주변의 개념을 설명하기 위해서입니다.기본적으로 다음과 같습니다.
- 분할 전에 원래 PID를 가져옵니다.이 PID는 분할 후에도 두 프로세스에서 동일하게 유지됩니다.
- 스플릿을 하다
- 분할 후 현재 PID를 얻습니다.이것은 두 프로세스에서 다릅니다.
이 답변도 보실 수 있습니다.fork/exec
★★★★★★ 。
(a) 제가 설명한 것보다 훨씬 더 복잡합니다.예를 들어, MINIX의 경우,fork
전체 프로세스 트리에 액세스할 수 있는 커널에서 실행됩니다.
부모 프로세스 구조를 자녀용 빈 슬롯에 복사하기만 하면 됩니다.
sptr = (char *) proc_addr (k1); // parent pointer
chld = (char *) proc_addr (k2); // child pointer
dptr = chld;
bytes = sizeof (struct proc); // bytes to copy
while (bytes--) // copy the structure
*dptr++ = *sptr++;
그런 다음 다음과 같은 선을 포함하여 적합하도록 하위 구조를 약간 수정합니다.
chld->p_reg[RET_REG] = 0; // make sure child receives zero
따라서 기본적으로는 제가 설정한 방식과 동일하지만 코드 경로 선택이 아닌 데이터 수정을 사용하여 발신자에게 반환할 항목을 결정합니다. 즉, 다음과 같은 결과가 나타납니다.
return rpc->p_reg[RET_REG];
fork()
부모 프로세스인지 자식 프로세스인지에 따라 올바른 값이 반환되도록 합니다.
®의 경우fork()
커널에서 발생합니다.실제 장소는 여기입니다.심플한fork()
시스템 콜은 다음과 같은 경우가 있습니다.
pid_t sys_fork() {
pid_t child = create_child_copy();
wait_for_child_to_start();
return child;
}
에는 'Kernel'이 있습니다.fork()
부모 프로세스로 한 번 돌아갑니다.단, 커널은 부모 프로세스의 복사본으로서 자녀 프로세스를 작성하기도 합니다.단, 일반 함수에서 복귀하는 것이 아니라 새로 생성된 자녀 프로세스의 스레드(및 프로세스)에 대해 새로운 커널 스택을 합성하여 작성합니다.새로 생성된 프로세스가 컨텍스트 스위치에서 돌아오면 그 스레드(및 프로세스)로 전환됩니다.ing 함수로 인해 하위 프로세스의 스레드가 0으로 사용자 모드로 돌아가게 됩니다.fork()
.
으로는 ★★★★★★★★★★★★★★.fork()
에 의해 스택에 in userland가 됩니다.커널이 스택에 넣은 값을 반환하거나 반환 레지스터에 넣습니다.에서 이 는 부모 에서 "0" 됩니다.read(2)
★★★★★★★★★★★★★★★★★★.
먼저 멀티태스킹이 어떻게 작동하는지 알아야 합니다.모든 세부사항을 이해하는 것은 유용하지 않지만 모든 프로세스는 커널에 의해 제어되는 일종의 가상 머신에서 실행됩니다. 프로세스에는 자체 메모리, 프로세서 및 레지스터 등이 있습니다.이러한 가상 객체를 실제 객체에 매핑(매직은 커널에 있음)하고 시간이 경과함에 따라 가상 컨텍스트(프로세스)를 물리적 머신으로 스왑하는 기계도 있습니다.
후 때('포크')fork()
는 커널에 대한 엔트리이며 부모 프로세스의 거의 모든 내용을 자식 프로세스에 복사하여 필요한 모든 내용을 수정할 수 있습니다.그 중 하나는 대응하는 구조를 변경하여 자식에 대해 0을 반환하고 부모에 있는 자식의 pid를 현재 콜에서 포크로 되돌리는 것입니다.
주의: 네더: "fork returns double"이라고 하면 함수 호출이 한 번만 반환됩니다.
클로닝 머신에 대해서 생각해 봅시다.혼자 들어가지만, 2명이 퇴장합니다.한 명은 사용자이고 다른 한 명은 클론입니다(매우 약간 다릅니다).클론을 클로닝하면 클론에는 사용자 이름과 다른 이름을 설정할 수 있습니다.
포크 시스템 호출에 의해 새로운 프로세스가 생성되고 부모 프로세스에서 많은 상태가 복사됩니다.파일 디스크립터 테이블, 메모리 매핑 및 그 내용 등이 복사됩니다.그 상태는 커널 내부에 있습니다.
커널이 모든 프로세스에 대해 추적하는 것 중 하나는 시스템콜, 트랩, 인터럽트 또는 컨텍스트스위치(대부분의 콘텍스트스위치는 시스템콜 또는 인터럽트에서 발생)에서 이 프로세스가 복원해야 하는 레지스터 값입니다.이러한 레지스터는 syscall/trap/interrupt에 저장된 후 userland로 돌아갈 때 복원됩니다.시스템 콜은 그 상태에 기입함으로써 값을 반환합니다.그게 포크가 하는 일이야부모 포크는 하나의 값을 얻고 자녀는 다른 값을 처리합니다.
분기된 프로세스는 상위 프로세스와 다르기 때문에 커널은 이 프로세스에 대해 무엇이든 수행할 수 있습니다.레지스터의 값이나 메모리 매핑을 지정합니다.반환값을 제외한 거의 모든 것이 부모 프로세스와 동일한지 확인하려면 더 많은 노력이 필요합니다.
실행 중인 각 프로세스에 대해 커널에는 컨텍스트 전환 시 로드백하기 위한 레지스터 테이블이 있습니다. fork()
을 사용하다특수 콜이 발신되면 프로세스가 컨텍스트스위치를 취득하여 콜을 실행하는 커널코드가 다른 (비활성) 스레드 내에서 동작합니다.
시스템 콜에 의해 반환되는 값은, 콜 후에 애플리케이션이 판독하는 특수한 레지스터(x86 의 EAX)에 배치됩니다.?fork()
호출이 이루어지면 커널은 프로세스의 복사본을 만들고 각 프로세스 기술자의 레지스터 테이블에는 적절한 값 0과 pid가 기록됩니다.
언급URL : https://stackoverflow.com/questions/36640260/how-does-fork-know-when-to-return-0
'programing' 카테고리의 다른 글
size_t는 C로 얼마입니까? (0) | 2022.08.10 |
---|---|
vuex 작업에 route.params.id 전달 (0) | 2022.08.10 |
모든 테스트가 최신 상태일 때 Gradle 테스트를 실행하는 방법 (0) | 2022.08.09 |
데이터 Firestore 생성 후 값 반환 방법 (0) | 2022.08.09 |
vuex 저장소의 상태를 모든 하위 구성 요소로 공유하는 방법 (0) | 2022.08.09 |