본문 바로가기

별걸다하는 IT/운영체제 OS

[운영체제]Static Linking vs Dynamic Linking(shared Library) 정적링킹 vs 동적링킹

반응형

운영체제 목차

 

Dynamic Linking을 이해하려면 Linking에 대해 이해를 하고 있어야하기 때문에 저번시간에 링킹에 대해서 포스팅을 했어요

 

링킹과정에서 오브젝트 파일을 라이브러리와 같이 Linking을 하는데 그 Linking을 하는 방법에 크게 두 가지가 있어요 

딱 감이오죠 ? Dynamic Linking과 Static Linking!

 

Static Linking이란?

일단 Static Linking이 이해하기 쉬운데 실행파일 만들 때 라이브러리를 같이 포함시켜서 .exe파일을 만드는 것을 Static Linking 즉 정적링킹이라고 합니다. 

 

예를 들어 출력할 때 cout이라는 클래스 라이브러리를 사용하잖아요 그 cout이라는 클래스 라이브러리를 실행하는 코드가 있겠죠. hello.exe에다가 집어넣어서 만든 것이 Static Linking입니다.

 

위키백과는 이렇게 정의하고 있네요 

정적 라이브러리는 루틴들과 외부 함수들 그리고 변수들의 집합으로서, 컴파일 타임에 호출자에 의해 리졸브되며 컴파일러와 링커에 의해 목적 파일과 독립된 실행 파일을 생성하기 위해 대상 애플리케이션에 복사된다.

 

그럼 정적 라이브러리를 실행파일에 추가시켜서 사용하는 정적링킹이의 단점이 무엇이길래 동적 링킹이라는 개념이 생겨났을까요?

 

정적링킹의 단점

 

정적 라이브러리를 사용하여 컴파일을 하면 링커가 프로그램이 필요로 하는 부분을 라이브러리에서 찾아 실행파일에다가 바로 복사합니다. 실행파일에 다 들어가기 때문에 라이브러리가 필요 없어요. 미리 컴파일 되어 있기 때문에 컴파일 시간도 단축됩니다. 또 직접 구현한 코드를 라이브러리화시켜서 기술 유출 방지로 사용할 수도 있어요.

 

하지만 실행 파일 내에 라이브러리 코드가 저장되기 때문에 메모리를 어마어마하게 잡아먹어요 

 

예를 들어, 멀티유저시스템인 LINUX, UNIX 운영체제의 경우에는 사태가 좀 더 심각(?)해집니다.

60명의 유저가 LINUX, UNIX서버에 접속해가지고 동시에 Hell world를 출력시키는 프로그램을 실행시킨다고 가정해봅시다.

리눅스 유닉스에서는 실행파일이 hello니까 (hello.exe가 아님) hello라는 프로그램을 실행시켰는데 얘가 정적링킹으로 만들어진 실행파일이예요

즉 여기서 출력하는데 사용된 cout이라는 클래스 라이브러리가 정적으로 링킹되어 있다는 것은 hello라는 실행파일에 cout클래스 라이브러리 코드가 다 들어가있다는 거죠. 즉 hello를 동시에 60명이 실행시키면 메모리에 cout 정보 코드만 60개가 존재하는거예요.. ㄷㄷㄷ  메모리가 매우 비효율적이죠? 그래서 만든 방법이 Dynamic Linking입니다. 

 

Dynamic Linking 동적링킹이란?

 

자 그럼 동적링킹은 뭐냐!

static linking을 써서 했더니 메모리에 쓸데없이 똑같은게 너무 많이 올라가더라 (static 단점에서 예를 들은 상황처럼!)

그래서 이 cout과 같이 많이 쓰이는 라이브러리는 메모리에 하나만 올리자

그리고 이 프로그램이 cout을 호출할 때 메모리에 있는 cout으로 점프해 그쪽으로 간 후 실행한 다음에 다시 돌아오게 하자!

이것이 Dynamic Linking입니다.

 

그래서 지금 현재 Linux, Unix에서는 프로그램을 개발할 때 별다른 옵션을 주지 않으면 Linking을 동적링킹으로 합니다.

Windows에서도 별다른 옵션을 주지 않으면 동적링킹을 해요 

 

동적 링크 라이브러리를 DLL (Dynamic-link Library)라고 합니다. 즉 윈도우에서 동적링킹할 때 사용되는 라이브러리 파일이예요.

그래서 DLL파일들이 보통 windows 시스템 디렉토리에 있어요. 

 

 

내가 hello world를 C++라이브러리랑 같이 링킹을 해서 실행을 했는데 메모리에 DLL파일이 없어, 그럼 실행을 못하니까 운영체제가 메모리에 DLL파일을 load시켜줍니다. 이렇게 메모리에 한 번 올라가면 그 다음부터는 이 올라가있는 DLL이 수행이 되는거예요 (즉 메모리에 cout이 60개가 잡히는 게 아니라 그림처럼 shared libraries 한 개만 잡히는거죠! )

 

따라서

Dynamic linked libraries are system libraries that are linked to user programs when the programs are run.

= Linking postponed until execution time

- 동적 라이브러리는 프로그램이 실행될 때 링크됩니다.

 

앞에 간단하게 설명 한 것을 좀 더 자세히 풀어쓰자면

With Dynamic Linking, a stub is included in the image for each library-routine reference. The stub is a small piece of code that indicates how to locate the appropriate memory-resident library routine or how to load the library if whether the needed routine is not already present. Stub replaces itself with the address of the routine, and executes the routine.

stub는 라이브러리가 메모리에 존재하지 않을 때, 라이브러리가 메모리에 상주할 수 있도록 라이브러리 루틴을 적절히 적재하는 방법을 알려주는 작은 코드 조각이예요. 

스텁은 모든 라이브러리 루틴에 들어있는데, A라이브러리의 a루틴이 호출되면 stub가 루틴 주소로 대체 돼, 다음에 그 코드가 한 번 더 수행될 때는 Dynamic linking없이 바로 주소를 참조해 실행할 수 있게 되는거예요.

다시 말해, 런타임시 해당 루틴이 불리면 그 스텁은 자신을 그 루틴이 들어있는 주소값과 바꿔치기 해버립니다. 한 번 루틴이 불리게 되면 스텁이 있었다는 사실은 사라지고 주소가 되어 한몸이 되는거죠. 여깄는 단 한 개의 원본을 사용하게 해줘서 메모리 절감 효과를 일으키는거예요.

즉 코드가 중복돼서 적재되지 않는다!

 

동적라이브러리를 윈도우에서는 DLL이라 부르고 Linux와 Unix에서는 dynamic linking library라 안부르고 Shared Library라고 합니다. 리눅스와 유닉스는 Shared Library라고 부르기 때문에 .so라고 쓰거나 .sa라고 씁니다. 그래서 그림이 *.so인거!

 

글 하나하나에 도움이 될 수 있도록 정성을 쏟았어요. 앞으로도 믿을 수 있는 좋은 정보 공유할 수 있는 블로거가 될게요. 비록 비영리 목적의 글이지만 글이 도움이 되신 분들은 광고 한번 클릭해주시면 포스팅을 작성하는 데 비글견처럼 힘이 넘칠 것 같습니다!!
 

동적 링킹의 단점

메모리의 요구사항이 훨씬 적어요. 정적 링킹의 경우 라이브러리 정보를 실행 프로그램당 메모리에 하나씩 다 올리지만 동적 링킹의 경우 동시에 유저가 프로그램을 몇 개를 실행시키던 한 개만 딱 올라가니까요.

 

동적링킹은 내 프로그램 영역에서 라이브러리가 저장되어 있는 주소로 점프하는 거잖아요 

이거는 먼 대로 점프하니까 성능상에서 당연히 약간의 overhead가 들겠죠.

 

또 Dynamic linking을 위한 불필요한 코드가 추가될거예요. 점프해야하니까!

성능상에서는 정적 링킹이 좋지만 메모리 관리차원에서는 동적 링킹이 좋습니다.

 

Shared Library 또는 dynamic library의 또 다른 장점은 여러분들이 실제 느껴봤을 텐데 

게임 프로그램을 만들 때 사용하는 많은 라이브러리가, 예를 들면 direct X라는 게임 library가 있어요

그 라이브러리를 사용한 게임을 내가  주고 샀어. 그런데 게임에 성능이 업그레이드가 되면 게임을 다시 사야 하잖아요

게임이 direct X 만들었는데 direct X라는 library 버전 up 되었어, 그럼 옛날에 내가 게임이 static linking이였다면 새로 버전업 direct X 새로 컴파일을 해서 새로 받거나 새로 사야 하죠. 

그런데 여러분 게임 업그레이드 할 때마다 새로 사나요? 아니죠? 그냥 업데이트 할뿐이잖아요 이게 바로 동적링킹 덕분입니다.

 

이게 만약 dynamic linking으로 direct X 만들어졌다면 

프로그램은 그대로 있지만 direct X 성능이 버전up 돼서 좋아졌으면 dynamic linking library 바꿈으로써 프로그램 성능능을 버전 UP시킬 수 있습니다. 동적 링킹은 이런 장점이 있어요 

 

Dynamic libraries are stored and versioned separately (DLL파일은 따로 저장돼요) 

원래 코드와 라이브러리가 별도로 있는거니까 블랙코드는 그대로 있고 library 버전업이 되면 그거에 대한 성능을 내가 그대로 받을 있다 거죠

 

 

동적링킹 여러분들이 알아야 하는거예요. 연습으로~ 여러분들이 집에서(이미 집인감..ㅎㅎ) 가장 쉬운 hello world cout 만들어 놓고 이걸 static linking으로 컴파일 했을때 나오는 .exe 디폴트인 dynamic linking으로 컴파일 했을 나오는 .exe 크기를 비교해보세요. 당연히 dynamic linking .exe파일의 크기가 엄청나게 작습니다.

 

현재는 정적라이브러리 동적라이브러리 둘다 섞어서 사용합니다.

여기서 정적링킹과 동적링킹 내용은 끝~~


공감과 댓글은 힘이됩니다 :)

 

 

 

반응형
  • tre 2019.05.21 19:18

    명료하고 깔끔한 설명 감사합니다 !

  • 11 2019.05.27 21:48

    와 정말 이해가 잘 됐어요! 감사합니다 정말로 ㅠㅠ

  • 123 2019.06.04 02:55

    정적 설명하실 때 동적으로 표기 되었던데 수정하시면 좋을 것 같아요!

    • 333 2019.06.23 11:20

      동감. 정적링킹 설명에 일부가 동적이라고 적혀있어 혼란이 야기되네요

  • 김동원 2019.06.08 22:50

    몰랑이말랑이님 귀하의 무궁한 발전을 기원합니다. 요약해주신 양질의 자료에 감사의 말씀을 드립니다. 항상 건강하시고 가정에 평안이 가득하시길.

  • 박성찬 2019.09.24 15:00

    설명이 너무 좋아요 감사합니다~

  • WhiskeySierra 2019.10.01 21:35 신고

    설명이 정말 아름답습니다. 잠깐 들어왔다가 지금 몇시간째야 올려주신 OS 자료 전부다 보고 있네요. 꼭 책으로도 출간해 주세요.

  • ㅎㅇ 2019.10.08 17:08

    오타 발견 했습니다. 한번 확인 부탁드려요.
    "리눅스 유닉스에서는 실행파일이 hello니까 (hello.exe가 아님) hello라는 프로그램을 실행시켰는데 얘가 동적링킹으로 만들어진 실행파일이예요
    즉 여기서 출력하는데 사용된 cout이라는 클래스 라이브러리가 동적으로 링킹되어 있다는 것은 hello라는 실행파일에 cout클래스 라이브러리 코드가 다 들어가있다는 거죠. 즉 hello를 동시에 60명이 실행시키면 메모리에 cout 정보 코드만 60개가 존재하는거예요.. ㄷㄷㄷ 메모리가 매우 비효율적이죠? 그래서 만든 방법이 Dynamic Linking입니다. "

    위에서 hellow 원시코드에서 cout 필요한 코드가 나오면 그 밑에 cout 라이브러리 원시코드를 복사하는게 정적링킹이라 했는데 "클래스 라이브러리가 동적으로 링킹되어 있다는 것은 " 동적으로 되어 있다 하셔서 확인 부탁드릴게요.

  • 익명 2019.10.09 01:07

    비밀댓글입니다

    • 양햄찌(jhnyang) 2019.10.09 10:13 신고

      안녕하세요! 제 게시글이 도움이 되었다니 보람되네요 :) 다만 카톡은 조금 부담스러워성..ㅠ 제가 회사에있는동안은 또 질문 답변을 잘 못드릴수도 있거든요 ㅎㅎ 언제든지 답글로 남겨주시면 매일 확인하고 있으니 도움이 되는거라면 답변드릴게요! :) 읽어주셔서 감사합니다

  • sdf 2019.11.19 22:23

    설명을 정말 잘 해주셨군요 ㅎㅎ 전공으로 운영체제 배우는 중에 막히는 부분이 있었는데 덕분에 이해가 수월해졌어요!!
    정말 감사합니다.^^

  • 구독합니다 2019.12.30 20:42

    구독합니당 ㅎㅎ

  • 초짜 2020.01.18 22:00

    아직 초짜라 나무보단 숲 위주로 건져내고 있습니다. 하하

  • 탑을노려 2020.02.01 19:33

    정리를 잘 해 놓으셔서 검색 후 한번 글을 읽기 시작하니까 멈출수가 없네요.
    감사합니다. 좋은 개발 오래 하시길 바랍니다.

  • Dux 2020.02.09 21:32

    와... 진짜 설명 잘하시네요. DLL이 그런 뜻이였구나
    비전공인데도 이해가 팍팍되네요

  • 전자계산기 2020.09.22 01:19

    코딩할때 맨날 DLL DLL 주구장창 쓰면서 무슨 뜻인지도 몰랐는데 이런 뜻인걸 처음 알았네요. 설명이 너무 좋아서 이해가 너무 잘됩니다 감사합니다~

  • 학생 2020.12.25 11:38

    이런 글 써주셔서 감사합니다. 포스팅을 읽기 전에는 제가 무엇을 모르는지 몰랐던 상태였는데 이제는 무엇을 공부해야 할지 깨달았어요. 덕분에 공부를 즐겁게 할 수 있을 것 같아요!

  • sun__ 2021.02.02 14:10 신고

    설명 정말 잘해주시네요. 감사합니다.

  • dd 2021.03.04 14:39

    오타 있어요 위에 static 링킹쪽에 동적이라고 적어두셨네요

  • c부터 배우자 2021.08.30 19:37

    맨날 보던 dll파일이 이런 의미였구나..ㅋㅋ 그리고 c언어 전처리기 파트글에선 컴파일전에 전처리기가 먼저 수행해서 include해준다음 컴파일로 알았는데 정적 링킹글에선 컴파일후 목적파일과 라이브러리(include)파일을 링킹해준대서 순서가 헷갈렸는데 이번글 보니까 include파일은 이미 컴파일 돼있으니 링킹만 필요한거였단걸 알았네요.

  • 너무 감사해요 2022.06.22 16:09

    감사합니다!! 근데 DLL에서 궁금했던 게 어떻게 이미 그 코드가 올라와있다는 것을 아는건가요?
    예를들어서 어떤 t1.exe를 실행하는데 여기에 c1.c 라는 파일이 있고 t2를 이제 실행하려고 하는데 c1.c라는 파일을 t2도 참고를 합니다.
    그러면 다이나믹 링킹으로 t2.ext에서 c1.c파일을 연결시켜줄껀데.. 어떻게 이미 그 파일이 존재하는지를 아는지..
    실행전에 그럼 메모리를 한 번 다 보는 건가요?