시스템 프로그래밍 2일차
Makefile & Make (리눅스 컴파일 환경)
GNU C compiler
- 대부분의 유닉스/리눅스에서 기본 컴파일러로 사용중
명령어: gcc
$ gcc [options] filename
- Options
- -c: object file(.o)만 생성
- -o: execution file name 지정 (default: a.out)
$ gcc test.c
$ ls
a.out test.c
$ gcc -o test test.c
$ ls
test test.c
# 오브젝트 파일은 실행 파일이 아니기 때문에 실행 안됨
$ gcc -c -o test.o test.c
$ ls
test.o test.c
Makefile & Make
Makefile
- Compile 방법을 기술 하는 파일
- 관련 파일 정보, compile 명령, 실행 파일명 등
- 여러 파일로 구성된 프로젝트 설정과 비슷한 개념
Make
- 주어진 Makefile에 따라 compile을 수행하고, 실행파일을 생성
- 최초 컴파일 이후에는, 변경이 있는 파일만 컴파일 함
컴파일 예제
$ gcc -c -o main.o main.c
$ gcc -c -o foo.o foo.c
$ gcc -c -o bar.o bar.c
$ gcc -o app.out main.o foo.o bar.o
Rule block
<Target>:<Dependencies>
<Recipe>
Target
- Build 대상 이름
- 일반적으로 최종 결과 파일명 사용
- Dependency
- Build 대상이 의존하는 Target이나 파일 목록
- Recipe
- Build 대상을 생성하는 명령어
Implict rules (Built-in rules)
- 자주 사용되는 규칙을 자동으로 처리 해줌
- Source (.c)를 compile해서 Object 파일(.o)를 생성하는 규칙
- 주의: Target에 대한 dependency 까지는 명시할 것
- 명시 하지 않은 파일이 수정된 경우, 수정 내용이 반영되지 않을 수 있음
변경전
app.out: main.o foo.o bar.o
gcc -o app.out main.o foo.o
main.o: foo.h bar.h main.c
gcc -c -o main.o main.c
foo.o: foo.h foo.c
gcc -c -o foo.o foo.c
bar.o: bar.h var.c
gcc -c -o bar.o bar.c
변경후
app.out: main.o foo.o bar.o
gcc -o app.out main.o foo.o bar.o
main.o: foo.h bar.h main.c
foo.o: foo.h foo.c
bar.o: bar.h bar.c
Variables (or Macro)
CC=gcc # 컴파일러 이름
OFLAGS=-g -Wall # 옵션
OBJS=main.o foo.o bar.o
TARGET=app.out
$(TARGET): $(OBJS)
$(CC) -o $@ $(OBJS) # $@ : $(TARGET) 정보가 자동으로 들어간다.
main.o: foo.h bar.h main.c
foo.o: foo.h foo.c
bar.o: bar.h bar.c
Clean rule
- Build로 생성된 파일들 삭제하는 규칙
- Clean build를 위해 사용 가능
clean:
rm -f *.o
rm -f $(TARGET)
$ make clean
Make file Basic pattern
CC=<compiler>
CFLAGS=<options for compiler>
LDFLAGS=<options for linker>
LDLIBS=<a list of library to link>
OBJS=<a list of object file>
TARGET=<build target name>
all: $(TARGET)
clean:
rm -f *.o
rm -f $(TARGET)
$(TARGET): $(OBJS)
$(CC) -o $@ $(OBJS)
파일 개요 & 기본 명령어 (파일 입출력 1/4)
File
File 이란?
- 보조 기억 장치에 저장된 연관된 정보들의 집합
- 보조 기억 장치 할당의 최소 단위
- Sequence of bytes (물리적 정의)
- OS는 file operation들에 대한 system call을 제공해야 함
- create, write, read, reposition, delete, Etc..
파일의 종류
Regular file (일반 파일)
- Text or binary data file
Directory
- Unix/Linux에서는 directory도 하나의 파일
Special file (특수 파일)
- 파일 형태로 표현된 커널 내 객체
- 데이터 전송, 장치 접근 시 사용하는 파일
기본 명령어 (생략)
File access permission (생략)
File I/O
Low-Level File IO (system call)
- system call을 이용해서 파일 입출력 수행
- File descriptor 사용
- Byte 단위로 디스크에 입출력
- 특수 파일에 대한 입출력 가능
High-Level File IO (Buffered IO)
- C Standard library를 사용해서 파일 입출력 수행
- File pointer 사용
- 버퍼(block) 단위로 디스크에 입출력
open (system call)
$ man -s 2 open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
pathname (file path)
- 열려는 파일의 경로 (파일 이름 포함)
flags (file state flags)
- 파일을 여는 방법(access mode) 설정
mode (file access permission)
- 파일을 새로 생성(O_CREATE) 할 때만 유효
Return: file descriptor
File descriptor
열려 있는 파일을 구분하는 정수(integer) 값
- 특수 파일 등 대부분의 파일을 지칭 가능
- Process별로 kernel이 관리
파일을 열 때 순차적으로 할당 됨
- Process 당 최대 fd 수 = 1,024 (default, 변경 가능)
Default fds (수정 가능)
- 0: stdin
- 1: stdout
- 2: stderr
flags (Man page 및 <sys/fcntl.h> 참조)
- 여러 플래그 조합 가능 (OR bit operation (|) 사용)
- read, write, RW
File table
열린 파일을 관리하는 표
- kernel이 process 별로 유지
- 열린 파일에 대한 각종 정보 관리
- Access mode, file offset, pointer to files
mode (Man page 및 <sys/stat.h> 참조)
- 파일 권한 설정 값 사용 (예, 644)
- 정의 된 플래그 사용
- 조합하여 사용 가능 (OR bit operation (|) 사용
조합 사용법
flag 조합의 예
- O_WRONLY | O_TRUNC
- O_RDWR | O_APPEND
mode 조합의 예
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
close (system call)
$ man -s 2 close
#include <unistd.h>
int close(int fd);
fd (file descriptor)
- 닫으려는 file descriptor
return
- 0: success
- -1: error
open & close 파일 완성
Makefile
CC=gcc
CFLAGS=-g -Wall
OBJS=fileOpenClose.o
TARGET=fileOpenClose.out
all: $(TARGET)
clean:
rm -f *.o
rm -f $(TARGET)
$(TARGET): $(OBJS)
$(CC) -o $@ $(OBJS)
fileOpenClose.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void) {
int fd;
mode_t mode;
mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // 644
fd = open("hello.txt", O_CREAT, mode);
if (fd == -1) {
perror("Creat"); exit(1);
}
close(fd);
return 0;
}
O_EXCL플래그 사용해 보기
- O_CREAT 옵션과 함께 사용할 경우 기존에 없는 파일이면 파일을 생성하지만, 파일이 이미 있으면 파일을 생성하지 않고 오류 메시지를 출력한다.
fd = open("hello.txt", O_CREAT | O_EXCEL, mode); # | O_EXCL 추가)
# 오류 메시지 확인
root@test-ubuntu:~/test# ./fileOpenClose.out
Creat: File exists
Error 핸들링
System call은 실패 시 -1 을 반환
Error code는 errno(변수)에 저장 됨
- error.h에 선언되어 있음 (special variable)
- extern으로 직접 접근 가능
- extern int errno;
perror(3)
- Error message를 출력 해주는 함수
$ man -s 3 perror
#include <stdio.h>
void perror(const char \*s);
Descriptor 할당
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int openFile(void) {
int fd = open("hello.txt", O\_RDWR);
if (fd == -1) {
perror("File Open");
exit(1);
}
return fd;
}
int main(void) {
int fd = 0;
fd = openFile(); printf("fd = %d\\n", fd);
close(fd);
close(0);
fd = openFile(); printf("fd = %d\\n", fd);
close(fd);
return 0;
}
출력
# 0: stdin
# 1: stdout
# 2: stderr
# oepnFile() --> fd=3
# close(0) --> 0(stdin) close 됨
# openFile() --> fd=0
root@test-ubuntu:~/test# ./fileOpenClose.out
fd = 3
fd = 0
'c언어 > 시스템 프로그래밍' 카테고리의 다른 글
시스템프로그래밍 - 4일차 (0) | 2023.04.08 |
---|---|
시스템 프로그래밍 3일차 (0) | 2023.03.31 |
시스템 프로그래밍 1일차 (0) | 2023.03.27 |