전형적인 포탄“포크 폭탄”은 정확히 어떻게 두 번 호출합니까?


15

Askubuntu와 다른 많은 Stack Exchange 사이트 에서 유명한 Fork Bomb 질문 을 겪은 후에 는 모든 사람들이 명백한 것처럼 말한 것을 이해하지 못합니다.

많은 답변 ( 최상의 예 )은 다음과 같이 말합니다.

" {:|: &}는 기능을 실행 :하고 출력을 :기능에 다시 전송 한다는 의미입니다.

음 의 결과는 정확히 무엇: 입니까? 다른 사람에게 전달되는 것은 무엇입니까 :?

그리고 또한:

본질적으로 당신은 매번 두 번 자신을 호출하고 자신 을 종료 할 방법이없는 함수를 만들고 있습니다.

정확히 두 번 실행 됩니까? 제 생각 :에는 첫 번째 :실행이 끝날 때까지 두 번째로 전달되는 것이 없으며 실제로는 결코 끝나지 않습니다.

C를 들어

foo()
{
    foo();
    foo(); // never executed 
}

두 번째 foo()foo()전혀 끝나지 않기 때문에 전혀 실행되지 않습니다 .

나는 같은 논리가 적용되는 것을 생각하고 :(){ :|: & };:

:(){ : & };:

같은 일을한다

:(){ :|: & };:

논리를 이해하도록 도와주세요.


9
파이프 라인의 명령은에서 병렬로 실행되며 :|:, 두 번째 명령 :은 첫 번째 명령이 완료 될 때까지 기다릴 필요가 없습니다.
cuonglm

답변:


26

파이핑은 다른 인스턴스가 시작되기 전에 첫 번째 인스턴스가 완료되도록 요구하지 않습니다. 실제로, 실제로하는 일은 첫 번째 인스턴스 의 stdout 을 두 번째 인스턴스의 stdin 으로 리디렉션하는 것이므로 포크 폭탄이 작동하기 위해 동시에 실행될 수 있습니다.

음의 결과는 정확히 무엇입니까 :? 다른 사람에게 전달되는 것은 무엇 :입니까?

':'는 다른 ':'인스턴스에 아무것도 쓰지 않고 stdout 을 두 번째 인스턴스 의 stdin 으로 리디렉션합니다 . 경우 그것의 실행 중에 뭔가를 쓰기 (그것은 결코 것이다, 그것은 아무것도하지만 자신을 분기하지 않습니다 이후)가에 갈 것 표준 입력 다른 인스턴스를.

stdinstdout 을 더미로 상상하는 데 도움이됩니다 .

stdin에 기록 된 내용은 프로그램이 읽기를 결정할 때 준비가되며 stdout 은 같은 방식으로 작동합니다.

이렇게하면 통신이없는 파이프 (두 개의 빈 파일) 또는 동기화되지 않은 쓰기 및 읽기와 같은 상황을 쉽게 상상할 수 있습니다.

정확히 두 번 실행됩니까? 제 생각 :에는 첫 번째 :실행이 끝날 때까지 두 번째로 전달되는 것이 없으며 실제로는 결코 끝나지 않습니다.

인스턴스의 입력 및 출력을 리디렉션하기 때문에 첫 번째 인스턴스를 시작하기 전에 두 번째 인스턴스를 완료 할 필요가 없습니다. 실제로 두 번째가 동시에 실행되어 두 번째가 첫 번째 데이터에 의해 구문 분석되는 데이터와 함께 작동하는 것이 실제로 바람직합니다. 이것이 여기서 일어나는 일이며, 첫 번째가 끝날 때까지 기다릴 필요없이 둘 다 호출됩니다. 이는 모든 파이프 체인 명령 행에 적용됩니다 .

동일한 논리가 : () {: | : &} ;:에 적용된다고 생각합니다.

:(){ : & };:

같은 작업을 수행

:(){ :|: & };:

첫 번째는 재귀 적으로 실행 되더라도 함수가 백그라운드에서 호출되기 때문에 작동하지 않습니다 ( : &). 첫 번째 :는 "자식" :이 끝나기 전에 기다릴 필요가 없으므로 결국 하나의 인스턴스 만 :실행하게됩니다. 만약 당신이 :(){ : };:그것을 가지고 있다면 , 첫 번째 :는 "자식" :이 돌아 오기를 기다리기 때문에, "자식" 이 돌아 오기를 기다리는 것 :입니다.

다음은 실행중인 인스턴스 수에 따라 다른 명령이 어떻게 표시되는지 보여줍니다.

:(){ : & };:

1 개의 인스턴스 (호출 :및 종료)-> 1 개의 인스턴스 (호출 :및 종료)-> 1 개의 인스턴스 (호출 :및 종료)-> 1 개의 인스턴스-> ...

:(){ :|: &};:

1 인스턴스 (2를 호출 :하고 종료)-> 2 인스턴스 (각 1을 호출하면 2 :와 종료)-> 4 인스턴스 (각 호출을 2 :와 종료)-> 8 인스턴스-> ...

:(){ : };:

1 개의 인스턴스 (호출 :및 리턴 대기)-> 2 개의 인스턴스 (자식이 다른 호출 :및 리턴 대기)-> 3 개의 인스턴스 (자식이 다른 호출 :및 리턴 대기)-> 4 개의 인스턴스-> ...

:(){ :|: };:

1 개의 인스턴스 (2를 호출 :하고 반환 될 때까지 기다립니다)-> 3 개의 인스턴스 (어린이는 :각각 2 개를 호출 하고 돌아 오기를 기다립니다)-> 인스턴스 7 개 (어린이는 :각각 2를 호출 하고 돌아 오기를 기다립니다) -> 15 개의 인스턴스-> ...

보시다시피 백그라운드에서 함수를 호출하면 (을 사용하여 &) 호출 된 함수가 반환되기 전에 수신자가 종료되므로 실제로 포크 폭탄이 느려집니다.


질문. 것 :(){ : & && : &}; :또한 포크 폭탄으로 작동? 당신은 또한 기하 급수적으로 증가 할 것이고, 사실, 당신은 : &그것을 더 빠르게 증가시키기 위해 여러 개의를 넣을 수 있습니다.
JFA

@JFA`─> $ : () {: & && : &}; :`는 구문 오류를 제공합니다 bash: syntax error near unexpected token &&' . 당신은 이것을 할 수 있습니다 : :(){ $(: &) && $(: &)}; :. 그러나 파이프 라인과 달리 병렬로 실행되지 않습니다. 어느 것과 같습니다 :(){: & };:. 확인하고 싶습니까? 이러한 시도 time $( $(sleep 1 & ) && $(sleep 1 &) )및이time $(sleep 1 | sleep 1)
세베루스 턱시도를

정확히,는 :(){ $(: &) && $(: &)};첫 번째 및 두 번째 인스턴스의 반환 값에서 논리 AND 연산을 실행하는 함수입니다. 문제는 논리적 AND가 두 값이 모두 참인 경우에만 참이므로 효율성을 위해 첫 번째 인스턴스 만 실행된다는 것입니다. 반환 값이 1이면 두 번째 인스턴스가 실행됩니다. 당신이 확인하려면 포크 폭탄은 더 빨리 생각 당신이 할 수처럼 체인에 단지 파이프 이상의 인스턴스:(){ :|:|: &}; :
IanC

부수적으로 다음과 같은 상황에서 많은 스크립트가 AND의이 동작을 사용합니다. if 문 ( if [ prog1 ]; then; prog2; fi) 을 수행하는 대신 쓰기 ( ) 할 수 prog1 && prog2있으며 prog2는 prog1의 리턴 값이 true 인 경우에만 실행됩니다.
IanC

자, 이것들은 모두 큰 포인트입니다. 내가 사용하는 &&전화에 apt-get update && apt-get upgrade, 그리고 &그들이 함께 작동하지 않습니다 좋은 점 SA 것을 '줄의 끝에서 백그라운드에서 실행하는 것이 아니라. 세미콜론은 앰퍼샌드와도 작동하지 않습니다.
JFA
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.