스레드간에 어떤 리소스가 공유됩니까?


264

최근에 나는 프로세스와 스레드의 차이점이 무엇인지 인터뷰에서 질문을 받았다. 정말 답을 몰랐습니다. 나는 잠시 생각하고 매우 이상한 답변을 주었다.

스레드는 동일한 메모리를 공유하지만 프로세스는 공유하지 않습니다. 이 질문에 답한 후, 면접관은 나에게 사악한 미소를 지었고 나에게 다음과 같은 질문을 주었다.

Q. 프로그램이 분할되는 부분을 알고 있습니까?

내 대답 : 네 (쉽게 생각했습니다) Stack, Data, Code, Heap

Q. 그렇다면 스레드가 공유하는 세그먼트는 무엇입니까?

나는 이것에 대답 할 수 없었고 그들 모두를 말하는 것으로 끝났다.

프로세스와 스레드의 차이점에 대해 정확하고 인상적인 답변을 제시 할 수 있습니까?


9
스레드는 동일한 가상 주소 공간을 공유하지만 프로세스는 공유 하지 않습니다.
Benoit

답변:


177

당신은 꽤 정확하지만 스레드 는 스택을 제외한 모든 세그먼트를 공유합니다 . 스레드는 독립적 인 호출 스택을 가지고 있지만 다른 스레드 스택의 메모리에는 여전히 액세스 할 수 있으며 이론적으로 다른 스레드의 로컬 스택 프레임에서 메모리에 대한 포인터를 보유 할 수 있습니다 (아마도 해당 메모리를 넣을 수있는 더 좋은 곳을 찾아야합니다!).


27
흥미로운 부분은 스레드에 독립적 인 호출 스택이 있지만 다른 스택의 메모리에 여전히 액세스 할 수 있다는 것입니다.
Karthik Balaguru

1
예-스레드간에 다른 스택의 메모리에 액세스 할 수 있는지 궁금합니다. 할당이 해제 된 스택을 참조하려고하지 않는 한 문제가 있는지 확실하지 않습니까?
bph

2
@bph : 그것은 가능한 다른 스레드의 스택 메모리에 액세스 할 수 있지만, 좋은 소프트웨어 공학 연습의 이익에, 나는 그것의 언급하지 않았다 허용 그렇게 할 수 있습니다.
Greg Hewgill

1
다른 스레드의 스택에 액세스하면 (특히 쓰기 작업) 여러 가비지 수집기 구현이 엉망입니다. 그러나 이것은 GC 구현의 결함으로 정당화 될 수 있습니다.
yyny 2014 년

56

에서 위키 백과 (: P 나는 그 면접관에 대한 정말 좋은 대답을 할 것이라고 생각)

스레드는 다음과 같은 점에서 기존 멀티 태스킹 운영 체제 프로세스와 다릅니다.

  • 스레드는 프로세스의 하위 집합으로 존재하지만 프로세스는 일반적으로 독립적입니다.
  • 프로세스는 상당한 상태 정보를 전달하는 반면 프로세스 공유 상태 내의 여러 스레드는 물론 메모리 및 기타 리소스
  • 스레드는 주소 공간을 공유하는 반면 프로세스에는 별도의 주소 공간이 있습니다.
  • 프로세스는 시스템 제공 프로세스 간 통신 메커니즘을 통해서만 상호 작용합니다.
  • 동일한 프로세스에서 스레드 간의 컨텍스트 전환은 일반적으로 프로세스 간의 컨텍스트 전환보다 빠릅니다.

2
위의 포인트 2 위 : 스레드의 경우 CPU도 컨텍스트를 유지합니다.
Jack

49

실제로 지적해야 할 것은이 질문에 대한 두 가지 측면, 즉 이론적 측면과 구현 측면이 있다는 것입니다.

먼저 이론적 인 측면을 보자. 프로세스와 스레드 간의 차이점과 프로세스간에 공유되는 것을 이해하려면 프로세스가 개념적으로 무엇인지 이해해야합니다.

Tanenbaum의 2.2.2현대 운영 체제 의 클래식 스레드 모델 에서 다음과 같은 내용이 있습니다 .

프로세스 모델은 리소스 그룹화 및 실행이라는 두 가지 독립적 인 개념을 기반으로합니다. 때때로 그것들을 분리하는 것이 유용합니다; 이곳은 실이 들어오는 곳입니다.

그는 계속한다:

프로세스를 보는 한 가지 방법은 관련 리소스를 그룹화하는 방법입니다. 프로세스에는 프로그램 텍스트와 데이터 및 기타 리소스가 포함 된 주소 공간이 있습니다. 이러한 리소스에는 열린 파일, 자식 프로세스, 보류중인 알람, 신호 처리기, 계정 정보 등이 포함될 수 있습니다. 프로세스 형태로 구성하면보다 쉽게 ​​관리 할 수 ​​있습니다. 프로세스가 갖는 다른 개념은 실행 스레드이며 일반적으로 스레드로 단축됩니다. 스레드에는 다음에 실행할 명령을 추적하는 프로그램 카운터가 있습니다. 현재 작업 변수를 보유하는 레지스터가 있습니다. 스택에는 실행 기록이 포함되어 있으며 각 프로 시저에 대해 하나의 프레임이 호출되었지만 아직 반환되지 않았습니다. 스레드는 일부 프로세스에서 실행되어야하지만 스레드와 프로세스는 서로 다른 개념이며 별도로 처리 할 수 ​​있습니다. 프로세스는 자원을 함께 그룹화하는 데 사용됩니다. 스레드는 CPU에서 실행되도록 예약 된 엔티티입니다.

아래로 그는 다음 표를 제공합니다.

Per process items             | Per thread items
------------------------------|-----------------
Address space                 | Program counter
Global variables              | Registers
Open files                    | Stack
Child processes               | State
Pending alarms                |
Signals and signal handlers   |
Accounting information        |

위는 스레드가 작동하는 데 필요한 것입니다. 다른 사람들이 지적했듯이 세그먼트와 같은 것은 OS 의존적 구현 세부 사항입니다.


2
이것은 훌륭한 설명입니다. 그러나 그것은 아마 어떻게 든 "대답"으로 간주 될 수있는 질문에 다시 연결해야한다
catalyst294

테이블과 관련하여 프로그램이 레지스터를 카운터하지 않습니까? 그리고 레지스터의 값으로 캡처 된 스레드의 "상태"? 나는 그들이 (프로세스 텍스트 포인터)를 실행하는 코드도 포인터를 놓친 거지
onlycparra

29

면접관에게 OS의 구현에 전적으로 달려 있다고 말한다.

예를 들어 Windows x86을 보자. 코드와 데이터의 세그먼트 [1] 만 있습니다 . 그리고 둘 다 전체 2GB (선형, 사용자) 주소 공간에 매핑됩니다. 기본 = 0, 제한 = 2GB 그들은 하나를 만들었지 만 x86은 세그먼트가 읽기 / 쓰기 및 실행이 될 수 없습니다. 그래서 그들은 두 개를 만들고 CS가 코드 설명자를 가리 키도록하고 나머지 (DS, ES, SS 등)는 다른 것을 가리 키도록 설정합니다 [2]. 그러나 둘 다 같은 것을 가리 킵니다!

당신을 인터뷰하는 사람은 자신이 진술하지 않았다는 숨겨진 가정을했고, 그것은 어리석은 속임수입니다.

따라서

Q. 그렇다면 어떤 세그먼트 스레드가 공유되는지 알려주십시오.

세그먼트는 적어도 Windows에서는 질문과 관련이 없습니다. 스레드는 전체 주소 공간을 공유합니다. 스택 세그먼트 SS는 1 개 뿐이며 DS, ES 및 CS와 동일한 기능을합니다 [2]. 즉 전체 피 묻은 사용자 공간 입니다. 0-2GB. 물론, 스레드에 스택이 1 개만있는 것은 아닙니다. 당연히 각각 고유의 스택이 있지만 x86 세그먼트는이 목적으로 사용되지 않습니다.

어쩌면 * nix는 다른 것을 할 수 있습니다. 누가 알아. 이 질문에 근거한 전제는 깨졌습니다.


  1. 최소한 사용자 공간 용.
  2. 보낸 사람 ntsd notepad:cs=001b ss=0023 ds=0023 es=0023

1
예 ... 세그먼트는 OS와 컴파일러 / 링커에 따라 다릅니다. 때때로 DATA 세그먼트와 별도의 BSS 세그먼트가 있습니다. 때때로 RODATA (읽기 전용으로 표시된 페이지에있을 수있는 상수 문자열과 같은 데이터)가 있습니다. 일부 시스템은 심지어 DATA를 SMALL DATA (기본 + 16 비트 오프셋에서 액세스 가능) 및 (FAR) DATA (액세스하는 데 필요한 32 비트 오프셋)로 분리합니다. 스레드별로 생성되는 추가 TLS DATA (Thread Local Store) 세그먼트가있을 수도 있습니다.
Adisak

5
아냐! 세그먼트와 섹션을 혼동하고 있습니다! 섹션은 링커가 설명 된대로 모듈을 부분 (data, rdata, text, bss 등)으로 나누는 방법입니다. 그러나 Intel / amd x86 하드웨어에 지정된 세그먼트에 대해 이야기하고 있습니다. 컴파일러 / 링커와 전혀 관련이 없습니다. 이해가 되길 바랍니다.
Alex Budovski

그러나 Adisak은 Thread Local 매장에 적합합니다. 스레드 전용이며 공유되지 않습니다. Windows OS를 알고 있으며 다른 OS를 확신하지 못합니다.
Jack

20

일반적으로 스레드를 경량 프로세스라고합니다. 메모리를 세 섹션으로 나누면 코드, 데이터 및 스택이됩니다. 모든 프로세스에는 자체 코드, 데이터 및 스택 섹션이 있으며이 컨텍스트 전환 시간으로 인해 약간 높습니다. 컨텍스트 전환 시간을 줄이기 위해 사람들은 스레드 개념을 생각해 냈습니다. 스레드 개념은 다른 스레드 / 프로세스와 데이터 및 코드 세그먼트를 공유하며 자체 STACK 세그먼트를 가지고 있습니다.


힙을 잊어 버렸습니다. 힙이 틀렸다면 스레드간에 공유되어야합니다.
Phate

20

프로세스에는 코드, 데이터, 힙 및 스택 세그먼트가 있습니다. 이제 스레드 OR 스레드의 IP (명령 포인터)는 프로세스의 코드 세그먼트를 가리 킵니다. 데이터 및 힙 세그먼트는 모든 스레드에서 공유합니다. 이제 스택 영역은 어떻습니까? 실제로 스택 영역은 무엇입니까? 스택이 힙 등보다 훨씬 빠른 방식으로 사용될 수 있기 때문에 프로세스가 스레드가 사용하기 위해 프로세스에 의해 작성된 영역입니다. 프로세스의 스택 영역은 스레드로 나뉩니다. 프로세스의 스택 영역은 3 개 부분으로 나뉘고 각각 3 개 스레드에 제공됩니다. 다시 말해, 각 스레드에 자체 스택이 있다고 말하면 해당 스택은 실제로 각 스레드에 할당 된 프로세스 스택 영역의 일부입니다. 스레드가 실행을 마치면 프로세스가 스레드 스택을 회수합니다. 사실로, 프로세스의 스택은 스레드로 분할 될뿐만 아니라 스레드가 SP, PC 및 상태 레지스터와 같이 사용하는 모든 레지스터 세트가 프로세스의 레지스터입니다. 따라서 공유와 관련하여 코드, 데이터 및 힙 영역은 공유되고 스택 영역은 스레드로 나뉩니다.


13

스레드는 코드와 데이터 세그먼트 및 힙을 공유하지만 스택은 공유하지 않습니다.


11
"스택의 데이터에 액세스 할 수 있음"과 스택을 공유하는 것에는 차이가 있습니다. 이 스레드에는 메서드를 호출 할 때 푸시 및 팝되는 자체 스택이 있습니다.
Kevin Peterson

2
둘 다 똑같이 유효한 견해입니다. 예, 모든 스레드는 스레드와 스택간에 일대일 대응이 있다는 의미에서 자체 스택을 가지고 있으며 각 스레드는 자체 일반 스택 사용에 사용되는 공간이 있습니다. 그러나 이들은 또한 완전히 공유 된 프로세스 리소스이며 원하는 경우 모든 스레드가 다른 스레드의 스택에 쉽게 액세스 할 수 있습니다.
David Schwartz

@DavidSchwartz는 다음과 같이 요점을 요약 할 수 있습니다. 모든 스레드에는 자체 스택이 있으며 스택은 2 부분으로 구성됩니다. 첫 번째 부분은 프로세스가 다중 스레드되기 전에 스레드간에 공유되며 두 번째 부분은 채워집니다. 소유 스레드가 실행 중입니다 .. 동의합니까?
FaceBro

2
@nextTide 두 부분이 없습니다. 스택은 공유됩니다. 각 스레드에는 자체 스택이 있지만 공유됩니다. 아마도 당신과 아내가 각각 차를 가지고 있지만 원하는 시간에 서로의 차를 사용할 수 있다면 좋은 비유가 될 것입니다.
David Schwartz

5

스레드는 데이터와 코드를 공유하지만 프로세스는 그렇지 않습니다. 스택은 둘 다 공유되지 않습니다.

프로세스는 메모리와보다 정확하게 코드를 공유 할 수도 있습니다 (예 : a 이후 Fork()). 이는 구현 세부 사항 및 운영 체제 최적화입니다. 여러 프로세스가 공유하는 코드는 코드에 처음 쓸 때 복제 될 것입니다 ( 복사시 복사 라고 함) . 스레드 코드의 정확한 의미에 대해서는 확실하지 않지만 공유 코드를 가정합니다.

           프로세스 스레드

   개인 전용 스택
   개인 정보 공유
   개인 코드   공유 1 공유 2

1 코드는 논리적으로 비공개이지만 성능상의 이유로 공유 될 수 있습니다. 2 100 % 확실하지 않습니다.


데이터와 달리 코드 세그먼트 (텍스트 세그먼트)는 대부분의 아키텍처에서 거의 항상 읽기 전용입니다.
호르헤 코르도바

4

스레드는 모든 것을 공유합니다 [1]. 전체 프로세스에는 하나의 주소 공간이 있습니다.

각 스레드에는 자체 스택 및 레지스터가 있지만 공유 주소 공간에서 모든 스레드의 스택을 볼 수 있습니다.

한 스레드가 스택에 일부 개체를 할당하고 다른 스레드로 주소를 보내면 둘 다 해당 개체에 동일한 액세스 권한을 갖습니다.


사실 방금 더 넓은 문제를 발견했습니다 . segment 라는 단어의 두 가지 용도를 혼란스럽게 생각합니다 .

실행 파일 (예 : ELF)의 파일 형식에는 고유 한 섹션이 있으며 컴파일 된 코드 (텍스트), 초기화 된 데이터, 링커 기호, 디버그 정보 등을 포함하는 세그먼트라고 할 수 있습니다. 힙 또는 스택 세그먼트가 없습니다. 이것들은 런타임 전용 구문이기 때문에 여기에 있습니다.

이들 이진 파일 세그먼트들은 상이한 허가들 (예를 들어, 코드 / 텍스트를위한 읽기 전용 실행 가능 및 초기화 된 데이터를위한 복사 중 기록 불가능)과 함께 프로세스 어드레스 공간에 별도로 매핑 될 수있다.

이 주소 공간의 영역은 언어 할당 라이브러리에 의해 적용되는 규칙에 따라 힙 할당 및 스레드 스택과 같은 다양한 목적으로 사용됩니다. 그것은 모두 메모리 일뿐이며 가상 8086 모드로 실행하지 않으면 세그먼트 화되지 않을 것입니다. 각 스레드의 스택은 스레드 생성시 할당 된 메모리 덩어리이며 현재 스택 최상위 주소는 스택 포인터 레지스터에 저장되며 각 스레드는 다른 레지스터와 함께 자체 스택 포인터를 유지합니다.


[1] 알겠습니다. 신호 마스크, TSS / TSD 등 모든 매핑 된 프로그램 세그먼트를 포함한 주소 공간은 여전히 ​​공유됩니다.


3

x86 프레임 워크에서 많은 세그먼트 (최대 2 ^ 16-1)를 나눌 수 있습니다. ASM 지시문 SEGMENT / ENDS가이를 허용하고 연산자 SEG 및 OFFSET은 세그먼트 레지스터의 초기화를 허용합니다. CS : IP는 일반적으로 로더에 의해 초기화되지만 DS, ES, SS의 경우 응용 프로그램이 초기화를 담당합니다. 많은 환경에서는 .code, .data, .bss, .stack 등과 같은 소위 "간단한 세그먼트 정의"를 허용하며 "메모리 모델"(작은, 큰, 소형 등)에 따라 로더가 세그먼트 레지스터를 초기화합니다. 따라서. 일반적으로 .data, .bss, .stack 및 기타 일반적인 세그먼트 (20 년 이후 로이 작업을 수행하지 않았으므로 모든 것을 기억하지 못합니다)는 하나의 단일 그룹으로 그룹화됩니다. 따라서 DS, ES 및 SS가 일반적으로 같은 영역이지만 이것은 단지 단순화하기위한 것입니다.

일반적으로 모든 세그먼트 레지스터는 런타임에 다른 값을 가질 수 있습니다. 따라서 인터뷰 질문은 옳았습니다. CODE, DATA 및 STACK 중 어느 것이 스레드간에 공유되는지 힙 관리는 다른 것입니다. OS에 대한 일련의 호출입니다. 그러나 임베디드 시스템과 같이 OS가 전혀 없다면 코드에서 여전히 새 / 삭제를 할 수 있습니까?

젊은이들에 대한 나의 충고-좋은 어셈블리 프로그래밍 책을 읽으십시오. 대학 커리큘럼은이 점에서 상당히 열악한 것 같습니다.


2

전역 메모리 외에도 스레드는 여러 가지 다른 속성을 공유합니다 (즉, 이러한 속성은 스레드에 국한되지 않고 프로세스에 전역 적입니다). 이러한 속성에는 다음이 포함됩니다.

  • 프로세스 ID 및 상위 프로세스 ID;
  • 프로세스 그룹 ID 및 세션 ID;
  • 제어 단자;
  • 프로세스 자격 증명 (사용자 및 그룹 ID);
  • 열린 파일 디스크립터;
  • 를 사용하여 생성 된 레코드 잠금 fcntl();
  • 신호 처리;
  • 파일 시스템 관련 정보 : umask, 현재 작업 디렉토리 및 루트 디렉토리;
  • 인터벌 타이머 ( setitimer()) 및 POSIX 타이머 ( timer_create());
  • 시스템 V 세마포어 실행 취소 ( semadj) 값 (섹션 47.8);
  • 자원 제한;
  • 소비 된 CPU 시간 (에서 반환 times());
  • 소비 한 자원 (에 의해 반환 됨 getrusage()); 과
  • (설정 nice 값 setpriority()nice()).

각 스레드마다 고유 한 속성은 다음과 같습니다.

  • 스레드 ID (섹션 29.5);
  • 신호 마스크;
  • 스레드 특정 데이터 (섹션 31.3);
  • 대체 신호 스택 ( sigaltstack());
  • errno 변수;
  • 부동 소수점 환경 (참조 fenv(3));
  • 실시간 스케줄링 정책 및 우선 순위 (섹션 35.2 및 35.3);
  • CPU 선호도 (35.4 절에서 설명 된 Linux 고유);
  • 능력 (제 39 장에서 설명 된 리눅스 특정); 과
  • 스택 (로컬 변수 및 함수 호출 연결 정보).

발췌 : Linux 프로그래밍 인터페이스 : Linux 및 UNIX 시스템 프로그래밍 핸드북, Michael Kerrisk , 페이지 619


0

스레드는 힙을 공유하지만 (스레드 특정 힙에 대한 연구가 있지만) 현재 구현은 힙을 공유합니다. (물론 코드)


0

스레드가 자체 스택을 가지고있는 동안 모든 스레드는 힙 메모리 등과 같은 시스템 리소스를 공유합니다.

따라서 모든 스레드는 프로세스를 위해 공유하는 힙 메모리 여야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.