프로세스 관련 스택은 무엇을 의미하나요?

프로세스 관련 스택은 무엇을 의미하나요?

책에서Unix 환경의 고급 프로그래밍Unix 계열 시스템의 스레드에 대해 다음을 읽었습니다.

프로세스 내의 모든 스레드는 동일한 주소 공간, 파일 설명자, 스택 및 프로세스 관련 속성을 공유합니다. 동일한 메모리에 액세스할 수 있으므로 불일치를 방지하려면 스레드 간에 공유 데이터에 대한 액세스를 동기화해야 합니다.

작가는 stacks여기서 무엇을 표현하고 싶은가? 저는 Java 프로그래밍 분야에서 일하고 있으며 각 스레드에는 자체 스택이 있다는 것을 알고 있습니다. 그래서 난 혼란스러워공유됨 stacks개념은 여기에 있습니다.

답변1

Unix 또는 Linux 프로세스의 맥락에서 "스택"이라는 문구는 두 가지를 의미할 수 있습니다.

첫째, "스택"은 제어 흐름에 대한 호출 순서의 후입선출 레코드를 나타낼 수 있습니다. 프로세스가 실행되면 main()먼저 호출됩니다. main()에 전화할 수 있습니다 printf(). 컴파일러에 의해 생성된 코드는 형식 문자열의 주소와 기타 매개변수를 printf()일부 메모리 위치에 씁니다. 그런 다음 코드는 printf()완료 후 제어 흐름이 반환되어야 하는 주소에 씁니다 . 그런 다음 코드는 호출 시작 부분으로 점프하거나 분기됩니다 printf(). 각 스레드에는 이러한 함수 활성화 레코드 스택 중 하나가 있습니다. 많은 CPU에는 스택을 설정하고 유지 관리하기 위한 하드웨어 지침이 있지만 다른 CPU(IBM 360 또는 다른 이름)는 실제로 주소 공간 전체에 분산될 수 있는 연결 목록을 사용합니다.

둘째, "스택"은 CPU가 함수에 인수를 쓰는 메모리 위치와 호출된 함수가 반환되어야 하는 주소를 나타낼 수 있습니다. "스택"은 프로세스 주소 공간의 연속된 부분을 나타냅니다.

Unix, Linux 또는 *BSD 프로세스의 메모리는 약 0x400000에서 시작하여 약 0x7fffffffffff(x86_64 CPU)에서 끝나는 긴 줄입니다. 스택 주소 공간은 가장 큰 숫자 주소에서 시작됩니다. 함수가 호출될 때마다 함수 활성화 레코드 스택이 "자라집니다". 프로세스 코드는 함수 매개변수와 반환 주소를 활성화 레코드 스택에 배치하고 프로세스의 현재를 추적하는 특수 CPU 레지스터인 스택 포인터를 감소시킵니다. 변수의 값은 스택의 주소 공간에 위치합니다.

각 스레드에는 자체 사용을 위해 "스택"(스택 주소 공간) 조각이 제공되며 스택을 함수 활성화로 기록합니다. 0x7ffffffffff와 더 낮은 주소 사이에 각 스레드에는 함수 호출을 위해 예약된 메모리 영역이 있습니다. 일반적으로 이는 하드웨어가 아닌 관례에 따라 시행됩니다. 따라서 스레드가 중첩된 함수 다음에 함수를 호출하는 경우 해당 스레드 스택의 맨 아래가 다른 스레드 스택의 맨 위를 덮어쓸 수 있습니다.

따라서 각 스레드에는 "스택" 메모리 영역이 있으며, 여기서 "공유 스택"이라는 용어가 유래되었습니다. 이는 프로세스 주소 공간을 단일 선형 메모리 블록으로 사용하고 "스택"이라는 용어를 사용한 결과입니다. 일부 오래된 JVM(매우 오래된)에는 실제로 스레드가 하나만 있다고 확신합니다. Java 코드의 모든 스레딩은 실제로 단일 실제 스레드에 의해 수행됩니다. 최신 JVM(Java 스레드를 실행하기 위해 실제 스레드를 호출하는 것)은 위에서 설명한 것과 동일한 "공유 스택"을 갖습니다. Linux 및 Plan 9에는 주소 공간의 일부와 다른 스택 주소 공간을 공유하는 프로세스를 설정할 수 있는 프로세스 시작 시스템 호출(Linux에서는 clone(), Plan 9에서는 rfork())이 있지만 이 스타일 스레드는 절대 정말 사로잡혔어요.

답변2

저자가 여기서 스택이란 무엇을 의미합니까? 저는 Java 프로그래밍 분야에서 일하고 있으며 각 스레드에는 자체 스택이 있다는 것을 알고 있습니다. 그래서 저는 여기서 공유 스택 개념에 대해 혼란스러워합니다.

복수형을 사용하는 것은 약간 이상하고 오해의 소지가 있는 것처럼 보입니다. 아마도 요점은 다중 스레드 프로그램의 여러 스택이 동일한 주소 공간을 공유한다는 것입니다.

Bruce Ediger가 설명하는 것처럼 "스택"은 데이터가 후입선출 방식으로 배치되는 연속 주소 공간의 단일 영역을 나타냅니다. 하지만,네이티브 스레드당프로세스에는 연속적인 영역이 있습니다. 프로세스 사이에 분할된 영역이 없습니다. 스레드 생성추가 스택을 할당해야 합니다.동일한 크기(고정된 숫자, 예를 들어 Linux의 기본값은 8MB)로 인해 너무 많은 멀티스레드 애플리케이션이 너무 많은 메모리를 소비합니다.

Java는 기본 스레드를 사용하여 Java 스레드를 구현하지만 커널과 관계없이 각 Java 스레드 자체에 대한 "스택"을 관리합니다. 이는 이 목적을 위해 일부 전역 메모리를 따로 설정하는 것을 의미합니다. 여기에서 가장 좋은 답변의 세 번째 부분을 참조하세요.

https://stackoverflow.com/questions/5483047/why-is-creating-a-thread-said-to-be-expense

물론 이는 특정 구현(openjdk)을 참조하지만 아마도 모두 이 작업을 수행해야 할 것입니다(내부 사용을 위해 "스레드 스택"으로 힙을 로컬로 할당).

각 기본 스레드에서 사용하는 개별 스택은 커널에 의해 관리되므로 이것이 전체 프로세스에 속하는 일부 전체 스택의 일부라는 Bruce의 암시에 동의하지 않습니다. 마찬가지로 단일(스레드가 아닌) 프로세스에는 하나의 스택만 있습니다. , 그러나 멀티스레드 프로세스의 메인 스레드확실히다른 스레드와 스택 공간을 공유합니다.

"공유 스택"은 모든 데이터가 단일 주소에서 시작하여 저장되는 스택을 의미합니다. 이는 동일한 스택을 공유하는 중첩 함수 호출을 의미합니다. 그러나 아래 Bruce가 언급한 예제 프로그램의 적응된 버전을 Linux 버전에서 사용합니다.pthread_create 매뉴얼 페이지매뉴얼 페이지:

./a.out one two three
In main() stack starts near: 0x7fff17b80f98
Thread 1: top of stack near 0x7f11ac6d3e78; argv_string=one
Thread 2: top of stack near 0x7f11abed2e78; argv_string=two
Thread 3: top of stack near 0x7f11ab6d1e78; argv_string=three

프로그램은 스레드 함수에서 지역 변수의 주소를 얻습니다. 제가 추가한 조정은 main()스레드를 생성하기 전에 동일한 작업을 수행하는 것입니다. 최근 64비트 Linux 시스템에서 실행하는 경우 스레드의 시작 주소는 정확히 8MB 떨어져 있으며 실제로는 기본 스레드 스택의 맨 위에서 멀리 떨어져 있습니다. 다음과 같이 중첩된 함수 호출과 대조해 보세요.

#include <stdio.h>

void eg (int n) {
    char *p;
    printf("#%d first variable at %p\n", n, &p);
    if (n < 3) eg(n+1);
}

int main(int argc, const char *argv[]) {
    char *p;
    printf("main() first variable at %p\n", &p);
    eg(1);
    return 0;
}

예제를 실행하세요:

main() first variable at 0x7fffef0aaf68
#1 first variable at 0x7fffef0aaf38
#2 first variable at 0x7fffef0aaf08
#3 first variable at 0x7fffef0aaed8

그것들은 단지 48바이트 떨어져 있습니다. 즉, 그것들은 사이에 사용되지 않은 공간 없이 서로 연속적으로 배치됩니다(다른 소량의 실제 데이터와 함께). 중첩된 재귀 없이 다중 스레드 프로그램에서 이것을 사용하지만 eg()각 스레드에서 한 번 호출되는 경우:

Thread 1: top of stack near 0x7f4bd5061e78; argv_string=one
Thread 2: top of stack near 0x7f4bd4860e78; argv_string=two
Thread 3: top of stack near 0x7f4bd405fe78; argv_string=three
#3 first variable at 0x7f4bd405fe48
#1 first variable at 0x7f4bd5061e48
#2 first variable at 0x7f4bd4860e48

각 변수는 세 개의 개별 스택 상단 근처에 위치합니다.

이 모든 것은 "스택 공간"이라는 상위 주소 영역에 있지만 멀티 스레드 프로그램에서는 다음과 같이 나뉩니다.다중 스택;대형 LIFO 구조로 취급되지 않습니다.

관련 정보