[고급 C++]C컴파일러와 C라이브러리(공유/정적/동적라이브러리)

 

 

  C 컴파일러

 

#include <stdio.h>
int main()
{
	printf("Hello World. \n");

	return 0;
}

 

컴파일러 종류

cc

유닉스에서 사용하는 표준 C 컴파일러

 

gcc

GNU C 컴파일러로 주로 리눅스 시스템에서 사용함

 

 

컴파일 과정

 

 

1) 전처리 과정

 #define, #include, #if와 같은 지시자 처리

 

2) 컴파일

전처리 작업을 수행한 소스 코드를 어셈블리 코드로 변환 후 오브젝트 파일로 변환

원시파일의 문맥과 문법을 확인하여 오류가 없으면 소스코드를 기계어 코드로 번역

 

3) 링크

오브젝트 파일과 라이브러리 함수를 연결하여 실행가능한 실행파일을 생성

 

 

CC컴파일 옵션

-o  : 실행파일 이름 지정

/data/it/it03]cc hello.c -o hello

/data/it/it03]ll

총 304

-rwxr-xr-x   1 it03       jsp          70112  9월 23일 10:05 hello

-rw-r--r--   1 it03       jsp             75  9월 23일 09:43 hello.c

drwxrwxrwx   2 it03       jsp             96  9월 23일 08:58 tmp

 

-c : 컴파일과 링크 분리

- 컴파일만 하고 링크를 수행하지 않음

- 오브젝트 파일만 생성

/data/it/it03]cc -c hello.c

/data/it/it03]ll

총 32

-rw-r--r--   1 it03       jsp             75  9월 23일 09:43 hello.c

-rw-r--r--   1 it03       jsp           2668  9월 23일 10:07 hello.o

drwxrwxrwx   2 it03       jsp             96  9월 23일 08:58 tmp

 

-O : 컴파일 최적화

- 실행속도를 향상시키며, 한번 컴파일된 실행파일은 지속적으로 사용되므로 중요

- 특히 O2 옵션은 가장 많이 사용하는 최적화 옵션으로  최적화, 수행되지 않는 코드 제거, 부분적 중복 제거, 연산 강도 경감 등 실행시간이 매우 줄어듦

 

 

 

[ 최적화 예시 (-O) ]

#include <stdio.h>

void delay(int count);
int main()
{
	printf("start. \n");
	delay(500000000);
    printf("end. \n");
    
    return 0;
}

void delay(int count)
{
	for (;count > 0; count--)
	
    continue;
}

 

[ 최적화 옵션 미사용 (-O0) ]

/data/it/it03]cc -O0 loop1.c

/data/it/it03]ll

총 256

-rwxr-xr-x   1 it03       jsp          70216  9월 23일 10:59 a.out

-rw-r--r--   1 it03       jsp            210  9월 23일 10:57 loop1.c

/data/it/it03]size a.out    // 실행파일시 사이즈크기

2848 + 24 + 32 = 2904

/data/it/it03]time a.out  // 실행시간 타임

start.

end.

real    0m3.80s

user    0m3.43s

sys     0m0.00s

 

[ 최적화 옵션 사용 (-O2)]

/data/it/it03]cc -O2 loop1.c

/data/it/it03]size a.out

2544 + 32 + 32 = 2608

/data/it/it03]time a.out

start.

end.

 

real    0m0.00s

user    0m0.00s

sys     0m0.00s

 

-S : C 소스를 어셈블리 코드로 확인

/data/it/it03]cc -S loop1.c

-rw-r--r--   1 it03       jsp          10851  9월 23일 11:02 loop1.s

/data/it/it03]vi loop1.s

    57  //file/line/col loop1.c/8/4

    58          add             out0 = 16, r32             // M [loop1.c: 8/4]

    59          add             r9 = @pltoff(printf), r0   // I [loop1.c: 8/4]

    60          add             r14 = r0, gp            ;; // I [loop1.c: 8/4]

    61          add             r9 = r9, gp             ;; // M [loop1.c: 8/4]

    62          ld8.acq         r10 = [r9]                 // M [loop1.c: 8/4]

    63          add             r9 = 8, r9              ;; // I [loop1.c: 8/4]

    64          ld8             gp = [r9]                  // M [loop1.c: 8/4]

    65          mov             b6 = r10                   // I [loop1.c: 8/4]

 

 

 

 

  라이브러리

C 라이브러리 

라이브러리 특성

컴파일 과정을 거쳐 만든 오브젝트 파일을 한 곳에 만들어 관리하는 아카이브 파일

라이브러리 = 목차(index) + (a.o + b.o + c.o +...)

- c 언어에서 자주 사용되는 함수는 라이브러리로 만들어 매번 컴파일할 필요없이 필요할때마다 사용 가능

- 컴파일 필요없이 링킹만 수행하므로 속도 빠름

- 목차보기 : ar - tv

 

 

표준 라이브러리

- 문자열 함수에 대한 선언 : <string.h>

- 문자함수 헤더파일 : <ctype.h>

- 날짜/시간 처리함수 <time.h>

- 동적 메모리함수 <stdlib.h>

 

사용자 정의 라이브러리

- 사용자가 정의하여 생성한 라이브러리

- 정적/동적/공유 라이브러리

 

 

정적 라이브러리

프로그램 실행 이전에, 즉 컴파일 과정의 링킹 단계에서 실행파일에 포함되는 라이브러리

 

특성

- 오브젝트 파일의 단순한 모음

- 컴파일시 적재되므로 라이브러리를 함께 배포할 필요가 없으며 바이너리 크기가 커짐

- 관리는 편하지만 프로세스마다 중복되어 메모리에 적재

 

생성 절차

① object 파일 생성

/data/it/it03]cc -c add.c   // 오브젝트 파일 생성

/data/it/it03]cc -c sub.c

/data/it/it03]cc -c mul.c

/data/it/it03]cc -c div.c

/data/it/it03]ll *.o

-rw-r--r--   1 it03       jsp           2700  9월 23일 13:30 add.o

-rw-r--r--   1 it03       jsp           2980  9월 23일 13:30 div.o

-rw-r--r--   1 it03       jsp           2732  9월 23일 13:30 mul.o

-rw-r--r--   1 it03       jsp           2700  9월 23일 13:30 sub.o

 

 

② 생성된 오브젝트파일을 아카이브 파일에 추가

- ar -r :  파일이 아카이브내에 존재하지 않으면 추가하고 존재하면 현재버전에 덮어씀

- ar -d : 파일 삭제

/data/it/it03]ar -r libcalc2.a add.o            // 오브젝트 파일 아카이브 파일에 추가

ar: libcalc2.a을(를) 만들고 있습니다.

/data/it/it03]ar -r libcalc2.a sub.o

/data/it/it03]ar -r libcalc2.a mul.o

/data/it/it03]ar -r libcalc2.a div.o

/data/it/it03]ll

-rw-r--r--   1 it03       jsp          11456  9월 23일 13:33 libcalc2.a

 

 

(기본 경로가 아니므로 라이브러리의 위치 명시) -L 옵션으로 디렉토리를 라이브러리 패스로 설정 필요

* 기본경로 : /lib, /usr/lib, /usr/local/lib

/data/it/it03]cc calc.c -lcalc2

// 라이브러리 경로 알수없으므로 에러 발생
ld: Can't find library for -lcalc2

Fatal error. 

 

/data/it/it03]cc calc.c -L. -lcalc2            // 라이브러리 패스 설정

/data/it/it03]a.out

x ? 100

y ? 30

100 + 30 = 130

100 - 30 = 70

100 * 30 = 3000

100 / 30 = 3

 

 

 

공유 라이브러리

프로그램 실행 시 실행파일에 포함되는 라이브러리

 

특성

- .so 확장자

- 실행시 적재하며 함수를 찾아야하므로 시간 소요

- 공유라이브러리를 사용하는 모든 프로세스들이 이미 메모리에 로드되어있는 하나의 공유라이브러리를 공유해서 사용

- 실행시 라이브러리를 적재하므로 프로그램 배포 시 공유라이브러리도 함께 배포해야함

 

생성 절차

① object 파일 생성

-ePIC 옵션은 위치에 독립적인 코드를 만들어줌

/data/it/it03]cc -c -ePIC add.c
/data/it/it03]cc -c -ePIC mul.c
/data/it/it03]cc -c -ePIC div.c
/data/it/it03]cc -c -ePIC sub.c

공유라이브러리는 ar이 아닌 cc 컴파일러에서 생성

/data/it/it03]cc -b -o libcalc3.so add.o sub.o mul.o div.o

/data/it/it03]ll

총 528

-rwxr-xr-x   1 it03       jsp          77832  9월 23일 13:52 libcalc3.so

 

※ 공유라이브러리 패스 설정

- LD_LIBRARY_PATH라는 환경변수를 통하여 경로를 읽어오기 때문에 경로가 설정되어야함

export LD_LIBARY_PATH=$LD_LIBRARY_PATH:/disk1/tutor1/lib

 

 

※ 실행파일이 요구하는 라이브러리 목록 확인

/data/it/it03]ldd a.out

a.out:

libcalc3.so =>  ./libcalc3.so

libc.so.1 =>    /usr/lib/hpux32/libc.so.1

libdl.so.1 =>   /usr/lib/hpux32/libdl.so.1

 

동적 라이브러리

프로그램 시작때가 아닌 실행중 로딩되는 라이브러리

 

특성

- 플러그인, 모듈 구현 시 적합

- 필요할 때까지 로드를 기다림

- API를 통해 사용

   * dlopen : 라이브러리 열기

   * dlsym : 함수 주소 반환

 

예제

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

void (*add)(int, int);  //함수포인터 변수 선언
void (*sub)(int, int);
void (*mul)(int, int);
void (*div2)(int, int);

int main()
{
	void *handle;
	int x, y;
	
	handle=dlopen("libcalc3.so",RTLD_LAZY);  //동적 라이브러리 load
	if(!handle)
	{
		perror(dlerror);
		exit(1);
	}

	add=(void (*)(int,int))dlsym(handle, "add");  //함수포인터 변수에 함수주소
	sub=(void (*)(int,int))dlsym(handle, "sub");
	mul=(void (*)(int,int))dlsym(handle, "mul");
	div2=(void (*)(int,int))dlsym(handle, "div");
	
	printf("x ? ");
	scanf("%d", &x);
	printf("y ? ");
	scanf("%d", &y);
	
	if(add) add(x,y);  //함수 포인터 변수를 사용하여 함수호출
	if(sub) sub(x,y);
	if(mul) mul(x,y);
	if(div2) div2(x,y);
	
	dlclose(handle);     //동적 라이브러리 닫기

	return 0;
}

 

 


 

시리즈 더 보기

[고급 C++]C컴파일러와 C라이브러리(공유/정적/동적라이브러리)

[고급 C++]조건 컴파일 / make

[고급 C++]포인터 1편(프로세스/포인터변수/포인터연산/NULL포인터)

[고급 C++]포인터 2편(배열과 포인터)

 

금한 사항은 댓글로 남겨주세요💃💨💫
좋아요와 구독(로그인X)은 힘이 됩니다 🙈🙉

 

 

 

 

 

반응형
그리드형

댓글

❤️김세인트가 사랑으로 키웁니다❤️