Search

만약 같은 프로그램을 실행할 경우

class
운영체제 심화
상태
완료
날짜
목차

만약 같은 프로그램을 동시에 실행할 경우 어떤 일이 발생할까요?

같은 프로그램을 여러 개 실행할 경우, 운영 체제와 메모리 관리의 관점에서 프로세스의 메모리 구조와 관련된 다양한 상황이 발생합니다.
이를 코드 영역, 프로세스 스택, 힙 영역으로 나누어 설명하겠습니다.

1. 코드 영역

공유 가능성 : 코드 영역에는 프로그램의 실행 가능한 기계어 명령이 저장됩니다.
대부분의 운영 체제는 메모리 매핑 기술을 활용하여 동일한 프로그램의 코드 영역을 여러 프로세스 간에 공유하도록 설계되어 있습니다.
예를 들어, Program.exe를 여러 번 실행하면, 동일한 코드 영역은 메모리에 한 번만 로드되고, 이를 모든 프로세스가 참조합니다.
이렇게 하면 메모리 사용량을 줄이고 프로그램 실행을 더 효율적으로 관리할 수 있습니다.

2. 프로세스 스택

프로세스마다 독립적 : 스택 영역은 함수 호출, 지역 변수, 매개변수 저장 등 각 프로세스의 실행 상태를 관리하기 위해 사용됩니다. 스택은 각 프로세스에 대해 독립적으로 생성되며, 한 프로세스의 스택이 다른 프로세스와 공유되지 않습니다.
같은 프로그램을 여러 번 실행해도 각 프로세스는 자신만의 스택을 가지고 독립적인 실행 흐름을 유지합니다.
예를 들어, 함수 호출이 겹치거나 스택 오버플로우가 발생하는 상황은 각 프로세스 내에서만 영향을 미칩니다.

3. 힙 영역

동적 메모리 할당 : 힙 영역은 동적으로 할당된 메모리를 저장하는 공간으로, 프로세스마다 독립적으로 생성됩니다.
한 프로세스에서 힙 영역에 데이터를 할당하거나 해제하더라도 다른 프로세스의 힙 영역에는 전혀 영향을 미치지 않습니다.
같은 프로그램을 여러 번 실행하면 각 프로세스는 독립적인 힙 공간에서 동작하며, 메모리 충돌이나 데이터 경합이 발생하지 않습니다.

그럼 C#의 Reflection.Emit를 사용해서 코드를 수정하면 어떻게 될까요?

Reflection.Emit을 사용해 런타임에 코드를 생성하고 실행하는 경우, 해당 코드는 메모리와 실행 흐름에서 독립적인 방식으로 동작합니다.
즉, 이러한 코드는 코드 영역이 아닌 힙 영역에서 실행되는 것입니다.

Reflection.Emit을 통한 코드 생성 및 실행

1.
IL 코드의 생성
Reflection.Emit은 동적으로 IL 코드를 생성하여 실행할 수 있도록 합니다.
생성된 코드는 런타임에 DynamicMethod, TypeBuilder, MethodBuilder 등을 통해 정의됩니다.
2.
메모리 영역에 로드
생성된 IL 코드는 JIT 컴파일러에 의해 컴파일되고, 메모리에 로드됩니다.
이때, 해당 코드는 프로세스의 메모리 공간에 동적으로 추가되며, 고유한 실행 컨텍스트를 가집니다.
동적 코드 전용 영역으로 관리됩니다.
이는 C#의 특별한 영역으로, 코드 영역이면서 동시에 힙 영역의 특성을 가집니다. 즉, 힙 영역에 존재하는 코드 영역이라고 할 수 있습니다.
3.
독립적 실행
동적으로 생성된 코드는 기존의 프로그램 코드와 독립적으로 실행될 수 있습니다.
이 독립성은 다음과 같은 요소로 인해 보장됩니다
동적 메서드는 자신만의 실행 스택을 사용합니다.
필요한 경우 런타임 환경에서 생성된 코드를 동적으로 메모리에서 해제하여 더 이상 접근할 수 없게 만듭니다.

그럼 Reflection.Emit로 변경한 코드를 dll파일로 제작해서 실행하면 해당 코드는 공유할 수 있는 것일까?

DLL로 변환된 코드를 저장하고 이후 해당 DLL을 실행할 경우, 코드를 여러 프로세스 간에 공유할 수 있습니다.

DLL 파일로 생성된 코드의 특징

1.
Reflection.Emit으로 생성된 코드 저장
Reflection.Emit을 사용하여 런타임에 생성한 코드가 AssemblyBuilder.Save() 메서드 등을 통해 디스크에 DLL 파일로 저장될 수 있습니다.
이 DLL 파일은 일반적인 .NET 어셈블리처럼 동작하며, 다른 응용 프로그램에서 참조하거나 로드할 수 있습니다.
2.
DLL 파일로 저장된 코드의 실행
저장된 DLL 파일은 정적 컴파일된 코드처럼 취급되며, 프로그램 실행 시 로드되어 코드 영역에 포함됩니다.
DLL을 로드한 각 프로세스에서 해당 DLL의 코드를 필요에 따라 메모리에 매핑합니다.
유니티 개발자의 경우 Reflection.Emit 기능을 웬만하면 사용할 수 없으므로 이 내용은 간단히 넘어가도 됩니다. 또한 모바일 개발자의 경우, Android나 iOS 환경에서는 일반적으로 같은 앱의 중복 실행을 제한하고 있어 동시에 같은 프로그램을 실행할 수 없습니다.