728x90
시스템 프로그래밍
- 운영체제, 하드웨어와의 상호작용을 프로그래밍 하는 것
- 커널이 제공하는 기능을 직접 제공받으며 low-level에서 동작하는 프로그램을 작성하는 것
- 커널이 제공하는 기능: 시스템 콜 주로 활용
- 운영체제, 네트워크 파트에서 학습한 내용을 소스코드 레벨에서 관측해보자.
- 타 프로그래밍 언어를 이용하더라도 공통적으로 사용될 시스템 프로그래밍 개념
- 파일 입출력
- 프로세스간 통신
- 소켓 프로그래밍
파일 디스크립터
- 프로세스는 운영체제로부터 파일을 할당받는다. 이걸 어떻게 구분할 수 있을까?
- 파일을 식별하기 위해 운영체제로부터 할당 받은 정보
- 입출력장치, 파이프, 소켓도 파일 디스크립터로 식별
- 마치 위에 장치들을 파일로 다룬다.
- 일반적으로 0이상의 정수 형태
- 프로세스가 파일을 열거나 생성할 때 운영체제는 해당 파일에 대한 파일 디스크립터 할당
- 저수준에서 파일을 식별하는 정보
- 고정된 파일 디스크립터 값
- 0번: 표준 입력
- 1번: 표준 출력
- 2번: 표준 에러
파일 디스크립터 반환받기(파일 열기)
open 메서드의 인자와 반환값이 유의미하다.
- Paramteter
- pathname: 파일 경로
- 절대 경로(root 기준)와 상대 경로(현재 기준)
- flag: 접근 플래그
- 어떻게 열지 결정하는 값
- 읽기 전용, 쓰기 전용, 읽기 쓰기 전용, 파일 생성,파일 내용 삭제 등등
- mode: 파일 생성시 모드
- 권한이 들어간다.
- 소유자에 대한 읽기 쓰기 등, 그룹에 대한 읽기 쓰기, 제 3자에 대한 권한 등
- Owner, Group, Other
- 읽기 4, 쓰기 2, 실행 1
- Owner 권한 4 + 2(읽고 쓰기)
- Group 권한 4 + 1(읽기 실행)
- Other 권한 4(읽기)
- pathname: 파일 경로
- Return
- 성공시 파일 디스크립터
- 실패시 -1
파일 디스크립터 (파일 닫기)
Paramter
- fd: 닫고자 하는 파일 디스크립터
Return
- 성공시 0
- 실패시 -1
open - close 예제 코드
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileDescriptor;
import java.io.IOException;
public class File_2 {
public static void main(String[] args) {
try {
String filePath = "example.txt";
// 파일 디스크립터로 파일 열기
FileInputStream fis = new FileInputStream(filePath);
FileDescriptor fd = fis.getFD();
// 파일 디스크립터 값 출력
System.out.println("파일 디스크립터 값: " + fd.toString());
// 파일 디스크립터를 이용한 파일 읽기
byte[] buffer = new byte[1024];
int bytesRead = fis.read(buffer);
System.out.println("파일 내용: " + new String(buffer, 0, bytesRead));
// 파일 닫기
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
파일 포인터
- 파일을 스트림처럼 읽고 쓰기 위한 자료형 → 편리한 함수 기능 많음
- 파일 디스크립트가 저수준에서 파일을 식별하는 정보라면 파일을 고수준에서 파일 식별 정보
https://www.gnu.org/software/libc/manual/html_node/Streams-and-File-Descriptors.html
파일 열기
Parameter
- pathname: 파일 경로
- mode: 파일 열기 모드
- r, w, a, r+, w+, a+ 등 여러가지 기능이 있음
Return
- 성공시 0
- 실패시 NULL
파일 닫기
Parameter
- stream: 파일 포인터
Return
- 성공시 0
- 실패시 EOF
파일 읽기
Parameter
- stream: 파일 포인터
- format: 입력 포맷
Return
- 성공시 입력받은 item 개수
- 실패시 EOF
파일에서 문자/문자열 읽기
문자 하나 읽기
Parameter
- stream: 파일 포인터
Return
- 성공시 읽은 문자
- 실패시 EOF
문자열 읽기
Parameter
- s: 문자열 버퍼
- size: 버퍼 크기
- stream: 파일 포인터
Return
- 성공시 문자열을 가리키는 포인터
- 실패시 NULL
파일 쓰기
Parameter
- stream: 파일 포인터
- format: 출력 형식
Return
- 성공시 쓰여진 바이트 값
- 실패시 음수 정수값
문자/문자열 읽기
Parameter
- c: 출력할 문자
- stream: 파일 포인터
Return
- 성공시 쓰인 문자
- 실패시 EOF
Parameter
- s: 출력할 문자열
- stream: 파일 포인터
Return
- 성공시 0이상의 정수
- 실패시 EOF
파일 쓰기
Parameter
- ptr: 출력할 바이트 포인터
- size: 출력 item 크기
- nmemb: 출력 item 개수
- stream: 파일 포인터
Return
- 출력된 item 개수
디렉터리 다루기
디렉터리 생성
Parameter
- pathname: 생성하려는 디렉터리의 경로
- mode: 생성하려는 디렉터리의 초기 접근 권한
- Owner, Group, Other로 분리된다.
Return
- 성공시 0
- 실패시 -1
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
int main() {
const char *dirname = "example_dir";
// 디렉터리 생성
if (mkdir(dirname, 0755) == 0) {
printf("디렉터리 생성 성공: %s\\n", dirname);
} else {
perror("디렉터리 생성 실패");
return 1;
}
return 0;
}
비어있는 디렉터리 삭제하기
Parameter
- pathname: 삭제하려는 디렉터리의 경로명
Return
- 성공시 0
- 실패시 -1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
const char *dirname = "example_dir";
// 디렉터리 삭제
if (rmdir(dirname) == 0) {
printf("디렉터리 삭제 성공: %s\\n", dirname);
} else {
perror("디렉터리 삭제 실패");
return 1;
}
return 0;
}
디렉터리 열기
Parameter
- name: 개방하려는 디렉터리의 경로명
Return
- 성공시 DIR 형 포인터 반환
- 실패시 NULL 반환
디렉터리 읽기
Parameter
- dirp: opendir로 개방한 디렉터리에 대한 포인터
Return
- 성공시 struct dirent 포인터 반환
- *DIR 는 디렉터리를 다루기 위한 핸들러
- struct dirent: 그를 통해 접근 가능한 디렉터리 엔트리
- 실패시 혹은 더 이상 읽을 디렉터리 항이 없을 경우 NULL 반환
하드링크와 심볼릭링크
아이노드
아이노드(i-node)라는 색인 블록을 활용한 파일 시스템
아이노드는 사실상 파일의 모든 것을 담고 있다
파티션 내 아이노드 영역
하드링크
- 하드링크 생성시 같은 아이노드를 공유하는 하드링크파일이 생성됨.
- 하드파일과 원본 파일은 이름만 다르지만 사실상 똑같다.
- 원본파일이 지워지면 하드파일을 조작할 수 있다.
- 하드링크는 같은 아이노드 번호를 가지는 파일 생성
- 하드 링크 파일은 원본 파일과 같은 데이터 공유원본 파일이 삭제/이동해도 하드 링크 파일은 남아 있음
- 하드링크는 같은 아이노드 번호를 가지는 파일 생성
- 여러 이름으로 파일을 참조하고 싶을 때
심볼릭 링크 파일 (= 소프트링크, 윈도우의 바로가기!)
- 심볼릭 링크 생성시 원본 파일을 가리키는 새로운 아이노드를 만든다
- 원본파일을 바라 보고 있는 파일이다.
- 원본파일이 지워지면 심볼릭 링크 파일을 조회 할 수 없다.
- 원본 파일과 같은 데이터를 공유하지 않음 (원본 파일의 위치만 알 뿐)
- 원본 파일이 삭제/이동하면 심볼릭 링크 파일은 사용 불가
- 심볼릭 링크는 원본 파일을 가리키는 파일 생성
- 하드 링크 파일에 비해 조작이 간편
- 복잡한 경로에 있는 파일을 참조하고자 할 때
하드링크 생성하기
Parameter
- oldpath: 생성하려는 디렉터리의 경로
- newpath: 생성할 하드 링크 파일 경로
Return
- 성공시 0
- 실패시 -1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
const char *originf = "original.txt";
const char *linkf = "linked.txt";
// 원본 파일 생성
FILE *file = fopen(originf, "w");
if (file == NULL) {
perror("원본 파일 생성 오류");
return 1;
}
fprintf(file, "원본 파일\\n");
fclose(file);
// 링크 생성
if (link(originf, linkf) == 0) {
printf("링크 생성 성공: %s -> %s\\n", linkf, originf);
} else {
perror("링크 생성 실패");
return 1;
}
return 0;
}
심볼릭링크 생성하기
Parameter
- target: 원본 파일 경로
- linkpath: 생성하려는 심볼릭링크 파일 경로
Return
- 성공시 0
- 실패시 -1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
const char *originalf = "original.txt";
const char *symlinkf = "symlink.txt";
// 원본 파일 생성
FILE *file = fopen(originalf, "w");
if (file == NULL) {
perror("원본 파일 생성 오류");
return 1;
}
fprintf(file, "원본 파일\\n");
fclose(file);
// 심볼릭 링크 생성
if (symlink(originalf, symlinkf) == 0) {
printf("심볼릭 링크 생성 성공: %s -> %s\\n", symlinkf, originalf);
} else {
perror("심볼릭 링크 생성 실패");
return 1;
}
return 0;
}
파일 속성 다루기
파일 (file)
- 보조기억장치의 의미있는 정보의 집합
- 구성요소
- 이름
- 실행하기 위한 정보
- 부가정보
파일(+ 디렉터리) 접근 단위: 블록(block)
- 섹터 단위로 접근하지 않음
728x90