리눅스 커널 공부하다보면 마치 당연히 알아야하는 것처럼 콜스택 콜스택 한다.
뭔 개소리여~
콜스택의 사전적인 말은
: 컴퓨터 프로그램에서 현재 실행 중인 서브루틴에 관한 정보를 저장하는 스택 자료구조이다.
콜 스택을 사용하는 목적은 여러 가지이지만, 주된 이유는 현재 실행 중인 서브루틴의 실행이 끝났을 때,
제어를 반환할 지점을 보관하기 위해서이다
기가막히게 어렵게 풀어 졌다.
실행중인 서브루틴에 관한 정보를 저장하는 스택 자료 구조?
안되겠다 단어로 쪼개서 이해해보자
서브루틴 이란 : 프로그램이 실행하는 Function 묶음 같은건가 그런것같다.
콜 이란 : 콜 말그래도 부른다 . 뭔가 부른다.
스택 이란 : 부르는걸 저장하는 구조 스택 ( 후입선출 , 데이터의 삽입과 출력이 리스트 한쪽에서만 이루어진다. ) 왜그럴까? 도대체 말이다.
프로그램이 함수를 호출을 저장하는 데이터 구조? 메모리?
중앙처리장치는 이 스택 메모리를 활용해 순차적으로 처리한다는 그런 순진한 의미일까??
인터넷 찾아보니 기똥차게 설명한 게있다 약 10% 이해할것만 같은 문장이다.
- 함수를 실행하면 콜스택이 1개 쌓인다.
- 함수 내에서 또 다른 함수를 실행하면 콜스택이 1개 더 쌓인다.
- 함수가 종료되면 함수 자신이 만든 콜스택이 줄어든다.
위키아저씨의 설명도 들어보자 아니 읽어보자
https://ko.wikipedia.org/wiki/콜_스택
위키 인용 아래 참고 :
콜 스택을 사용하는 목적은 여러 가지이지만,
주된 이유는 현재 실행 중인 서브루틴의 실행이 끝났을 때, 제어를 반환할 지점을 보관하기 위해서이다.
실행 중인 서브루틴은, 호출되어서 그 실행이 아직 완료되지는 않았지만, 완료후에는 호출된 지점으로 제어를 넘겨야 한다.
서브루틴의 이러한 실행은 여러 단계로 중첩될 수도 있는데, 다른 호출에 의해 또 다른 서브루틴으로 넘어가버리거나,
재귀같은 특별한 경우가 있다. 이러한 중첩의 특성 때문에 스택 자료구조를 사용하는 것이다.
예를 들어 만약 DrawSqure 라는 서브루틴이 있고 DrawSquare 가 DrawLine을 호출한다고 해보자.
(Square는 Line 4개니까 4번 호출하게 될 것이다.)
DrawLine 서브루틴은 자신이 호출된 뒤 어디로 돌아가야할지 알고 있어야만 한다.
(그래야 4번만 불릴 것이다.)
이를 구현하기 위해, 메모리 주소가 서브루틴이 끝날 때 반환 주소(return address)를 확인하도록 하고,
이를 위해 서브루틴 호출시 콜 스택에 반환 주소를 제일 먼저 집어넣는다.
오오오 뭔가 이해할것같다.
이정도만 이해하고 디버깅챕더에서 연습하면 머리에 들어올것같다.
끝내기전에 MDN 의 개념도 한번 읽어보고 끄도록합시다.
여러 함수들을 호출하는 스크립트에서 해당 위치를 추적하는 인터프리터 (웹 브라우저의 자바스크립트 인터프리터같은)를 위한 메커니즘입니다.
현재 어떤 함수가 동작하고있는 지, 그 함수 내에서 어떤 함수가 동작하는 지, 다음에 어떤 함수가 호출되어야하는 지 등을 제어합니다.
- 스크립트가 함수를 호출하면 인터프리터는 이를 호출 스택에 추가한 다음 함수를 수행하기 시작합니다.
- 해당 함수에 의해 호출되는 모든 함수는 호출 스택에 추가되고 호출이 도달하는 위치에서 실행합니다.
- 메인 함수가 끝나면 인터프리터는 스택을 제거하고 메인 코드 목록에서 중단된 실행을 다시 시작합니다.
- 스택이 할당된 공간보다 많은 공간을 차지하면 "stack overflow" 에러가 발생합니다.
예제
function greeting() {
// [1] Some codes here
sayHi();
// [2] Some codes here
}
function sayHi() {
return "Hi!";
}
// Invoke the `greeting` function
greeting();
// [3] Some codes here
위 코드는 다음과 같이 실행될 것입니다.
- greeting() 함수에 도달할 때까지, 모든 함수를 무시합니다.
- greeting() 함수를 호출합니다.
- greeting() 함수를 호출 스택 리스트에 추가합니다.
호출 스택 리스트:
- greeting
4. `greeting` 함수 내부의 모든 코드를 실행합니다
5. sayHi() 함수를 얻습니다.
6. sayHi() 함수를 호출 스택 리스트에 추가합니다.
호출 스택 리스트:
- greeting
- sayHi
7. sayHi() 함수의 끝에 도달할 때까지, 함수 내부의 모든 코드를 실행합니다.
8. sayHi() 가 호출된 라인으로 돌아와 greeting() 함수의 나머지를 계속 실행합니다.
9. 호출 스택 리스트에서 sayHi() 함수를 제거합니다
호출 스택 리스트:
- greeting
10. greeting() 함수 내부의 모든 코드가 실행되었을 때, 이를 호출한 라인으로 돌아와 JS 코드의 나머지를 계속 실행합니다.
11. 호출 스택 리스트에서 greeting() 함수를 제거합니다.
호출 스택 리스트:
EMPTY
우리는 빈 호출 스택으로 시작하며, 함수를 호출할 때마다 자동으로 호출 스택에 추가되고, 해당 코드가 모두 실행된 후, 호출 스택에서 자동으로 제거됩니다. 결국, 마찬가지로 빈 호출 스택으로 끝납니다.
- 대박예제입니다.
모두 이해했으리라 믿습니다.
https://developer.mozilla.org/ko/docs/Glossary/Call_stack
'Unix & Linux' 카테고리의 다른 글
WIFI SSID , 제거하기 (0) | 2022.02.04 |
---|---|
나만의 리눅스 만들기 , 웰컴메시지 수정 ( etc/motd) (0) | 2022.01.29 |
자꾸보는, 리눅스 커널 소스의 구조 (0) | 2022.01.21 |
원론적인 이야기를 해보자, 리눅스 인기 비결 (0) | 2022.01.21 |
원론적인 이야기를 해보자, 리눅스의 역사 ( UNIX, LINUX ?? ) (0) | 2022.01.21 |