학교 강의를 복습하는 차원에서 작성하는 글입니다.
학부생 수준의 글이므로, 오류가 있을 수 있는 점 양해바람니다.
기존 프로그래밍 환경
통합개발환경 IDE
에디터 + 빌더 (= 컴파일러 + 링커) + 디버거
에디터
소스 코드를 편집하는 용도로 사용
컴파일러
소스 코드를 바이너리 코드로 변경한다.
리눅스 시스템에서는 gcc를 사용한다.
링커/로더
목적 파일들을 연결해서 실행 파일을 만든다.
리누긋 시스템에서는 ld를 사용한다.
디버거
한줄씩 실행 / 메모리 추적 등 디버깅에 사용한다.
Linux의 프로그래밍 환경
통합개발환경 IDE
에디터 + 빌더 (= 컴파일러 + 링커) + 디버거
에디터는 따로 존재
gedit, xed, vim, vscode ...
컴파일러
gcc (GNU C Compiler -> GNU Compiler Collection) 이름 변경됨
링커
Id (GNU Linker)
디버거
gdb (GNU debugger)
컴파일 및 실행 과정
1. Preprocessor
#define을 파일 내용으로 바꾸는 과정 , #include "a.c" => a.c 파일을 열어서 내용을 덮어씌워라.
Programmer가 소스 코드 작성함.
2. Compiler
Compile, C 소스 코드를 Assembly source code로 바꿔줌.
=> Assembly까지는 읽을 수 있는 텍스트 파일
3. Assembler
코드 내용을 전부 16진수(기계어)로 바꿔준다.
역으로 Object code를 Assembly code로 바꿔줄 수 있다. 그러나 C로는 못 간다.
4. Archiver / Linker
컴파일을 빨리 하기 위해 작성해야 하는 코드들을 Object code로 만들고 묶어서, Library로 만들어둔다.
그걸 lInker가 하나의 실행 파일로 만든다.
5. Loader
제작된 파일을 메모리에 올린다.
==>
source code => (compiler) => Assembly source code => (Assembler) => object code (*.out) => (linker) => (loader) (*.elf)
* gcc 사용
gcc [options] source_files
[options]
-o : 실행파일을 만들 경우 실행 파일의 이름을 지정한다.
-c : 지정한 소스코드의 목적(Object) 파일을 만든다.
ex)
gcc -o hello.elf hello.c
=> hello.c 파일을 hello.elf 라는 실행 파일로 만든다.
gcc hello.c
=> a.out(기본 출력 파일), object 파일이 만들어진다.(목적 파일은 실행 되지 않는다.)
컴파일
큰 소스 코드가 있다고 할 때, 전체를 매번 컴파일 하기에는 시간이 많이 든다.
따라서, 새로 수정해서 추가 할 코드만 컴파일 하고, 나머지는 미리 Object Code로 만들어 둔다.
소스 코드를 컴파일 할때 오류가 있는 경우, gcc는 오류 메세지를 출력한다.
큰 규모의 프로그램은 여러 개의 소스 코드로 나누어서 작성하는 것이 일반적이다.
ex) gcc -o three one.c two.c
=> three 파일이 생성된다.
gcc main.c
=> Default로 a.out 파일이 main.c 컴파일 결과값이 된다.
gcc main.c -o main.elf
=> main.elf가 결과값. (중간에 main.o 라는 Object 파일이 있었다.)
gcc main.c printf.c scanf.c -o main.elf
=> main.c & printf.c & scanf.c => main.elf 가 됨(증분 컴파일)
gcc main.c -c
=> main.o 굳이 -c 옵션으로 목적 파일까지만 생성
gcc main.o printf.o scanf.o -o main.elf
=> 굳이 목적 파일에서 다시 실행파일 만듦
gcc main.c printf.o scanf.o -o main.elf
=> 목적 파일이랑 소스 코드 같이 실행 파일로 생성
*
gcc mian.c -c
gcc main.o printf.o scanf.o -o main.elf
=> 소스 코드 일부분만 수정 후 실행 파일 생성
정적 링킹 VS 동적 링킹
정적 링킹(Static Linking)
static 라이브러리용 오브젝트 코드 생성
gcc --static -c -o printf.o printf.c
=> 목적 파일을 만들 때 --static 옵션을 주어서 최종적으로 static 라이브러리를 만듦, printf.o 생성
ar rc libinout.a printf.o scanf.o
=> libinout.a , static 라이브러리 확장자는 .a 이다. printf.o scanf.o 를 묶어서 Static 라이브러리 만듦
main.c 파일을 수정한 후, static 라이브러리와 실행파일 생성
gcc main.c -l inout -L. -o main.elf
=> 소문자 -l 로 라이브러리 inout , 대문자 -L 로 라이브러리 찾는다. 이를 통해 printf.o 와 scanf.o 를 우겨넣는다.
-L. => . 현재 위치에서 라이브러리를 찾는다.
동적 링킹(Dynamic Linking)
Dynamic 라이브러리용 오브젝트 코드 생성
gcc -o printf.o -shared -fPIC -c printf.c
=> printf.o 생성, Dynamic 라이브러리 용 옵션 -shared -fPIC 이다.
gcc -o libinout.so -shared -fPIC printf.o scanf.o
=> gcc 쓰되 -o 옵션 쓰고. -shared -fPIC + 앞에서 생성한 목적 파일
libinout.so 는 dynamic 라이브러리가 된다. dynamic 라이브러리 확장자는 .so 이다.
main.c 파일을 수정 후 dynamic 라이브러리와 실행파일 생성
gcc main.c -l inout -L. -o main.elf
=> 라이브러리와 실행 파일 생성은 정적 라이브러리와 동적 라이브러리 동일.
단 동적 라이브러리의 경우 main.elf에 -l inout 정보가 담겨 있다. 그래서 실행할 때, 찾아서 가져다 써.
실행 파일 크기가 줄어든다.
Static Linking 으로 만들어진 실행파일 실행하는 경우
./main.elf
=> main.elf(main.o + libinout.a) 전체 다 리눅스 커널이 DISK로 부터 Memory로 복사함
Dynamic Linking 으로 만들어진 실행파일 실행하는 경우
./main.elf
=> main.elf를 일단 복사한뒤, memory에서 libinou.so를 가져와야 하는걸 알아차리면.
DISK로부터 복사해온다. 이떄 기존 복사한 값이 있는 경우. Memory에서 그걸 사용한다.
==> 따라서, Static Linking 으로 만들어진 실행파일을 실행하는 경우.
라이브러리가 중복되어도. 또 복사해 사용해야 하므로 메모리 낭비가 발생한다.
===> 리눅스 상에서는 우선 Dynamic Linking 실행하고 없으면, 그 다음에 Static Linking으로 해보고. 그래도 없으면 없다고 알려준다.
Static Library 제작과 사용
제작
gcc --static -c -o a.o a.c
gcc --sattic -c -o b.o b.c
gcc --sattic -c -o c.o c.c
ar rc library.a a.o b.o c.o
사용
-l 옵션으로 라이브러리 파일을 지정한다. (lib 과 .a는 빼고 지정)
라이브러리 위치는 -L로 지정한다. 현재 폴더 안에 경우 -L.
=> gcc main.c -l rary -L.
장점 : 파일 하나만으로 최종 결과물이 된다.
단점 : 메모리를 많이 잡아먹고, 전체 코드 크기가 커진다.
Dynamic Library 제작과 사용
제작
gcc -o library.so -shared -fPIC a.c b.c c.c
or
(증분 컴파일)
gcc -o a.o -shared -fPIC -c a.c
gcc -o b.o -shared -fPIC -c b.c
gcc -o c.o -shared -fPIC -c c.c
gcc -o library.so -shared -fPIC a.o b.o c.o
사용
-l 옵션으로 라이브러리 파일을 지정, lib과 .so는 빼고 지정
라이브러리 위치는 -L로 지정. 현재 폴더 안은 -L.
=> gcc main.c -l rary -L.
장점 : 라이브러리만 수정하는 것이 가능, 전체 크기가 줄어든다.
단점 : 파일 여러 개가 필요하다. 실행 속도가 약간 줄어든다.
'프로그래밍 > Linux' 카테고리의 다른 글
[Linux]Debug (0) | 2023.10.08 |
---|---|
[Linux]컴파일 make (0) | 2023.10.08 |
[Linux]리눅스 디렉토리 (트리 구조) (1) | 2023.10.08 |
[Linux]리눅스 커널 (0) | 2023.09.17 |
[Linux]&&とは (0) | 2023.02.27 |