2강-1. 파일 개요 & 기본 명령어
File
- 보조 기억 장치에 저장된 연관된 정보들의 집합
- 보조 기억 장치 할당의 최소 단위
- Sequnce of bytes (물리적 정의)
- File operations
- Create, Write, Read, Reposition, Delete, …
- OS는 file operation들에 대한 system call을 제공해야 함
Types of files in Unix/Linux
- Regular file (일반 파일)
- Text or Binary data file
- Directory
- Unix/Linux에서는 디렉토리도 하나의 파일
- Special file (특수파일)
- 파일 형태로 표현된 커널 내 객체
- 자원에 대한 시스템 내부적 표현
- 데이터 전송, 장치 접근 시 사용하는 파일
- device files, pipes, socket, …
- 파일 형태로 표현된 커널 내 객체
Basic commands for file
- ls (list)
- 현재 디렉토리 내 파일 목록 출력
-l
: 상세 파일 정보 출력-a
: 모든 파일(숨겨진 파일 포함) 목록 출력
- touch
- 빈 파일 생성 or 변경된 날짜 수정
- rm
- 파일 삭제
-r
: 디렉토리 삭제
- cat (concatenate)
- 파일 내용 출력
- cp (copy)
- 파일 복사
cp 원본 복사본
-r
: 디렉토리 복사
- mv (move)
- 파일 이동 or 이름 변경
mv 원본 이동본
File access permission
- 소유자(Owner), 그룹(Group), 기타(others) 사용자에 따라
읽기(r), 쓰기(w), 실행(x) 권한을 가짐
- chmod (change mode)
- 파일 권한 변경
chmod 권한 대상
chmod u+r 대상
: 소유자에게만 읽기 권한을 줌
2강-2. File open & close
Low-level vs High-level file IO
Low-Level File IO (System call)
- System call을 이용해서 파일 입출력 수행
- File descripor 사용
- Byte 단위로 디스크에 입출력
- 특수 파일에 대한 입출력 가능
High-Level File IO (Buffered IO)
- C Std Lib를 사용해서 파일 입출력 수행
- File pointer 사용
- 버퍼(block) 단위로 디스크에 입출력 (여러 형식의 입출력 지원)
Opening Files - open(2)
1
2
3
4
5
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags [, mode_t model]);
- pathname: 열려는 파일의 경로 (파일 이름 포함)
- flags (file state flags): 파일을 여는 방법(access mode) 설정
- mode (file access permission): 파일을 새로 생성(
O_CREATE
)할 때만 유효 - return: file descriptor (int)
File descriptor
- 열려 있는 파일을 구분하는 정수값
- 특수 파일 등 대부분의 파일을 지칭 가능
- Process별로 kernel이 관리
- 파일을 열 때 순차적으로 할당 됨
- Process 당 최대 fd 수 = 1024(default, 변경가능)
- Default fds (수정 가능)
- 0: stdin
- 1: stdout
- 2: stderr
- flags (
|
로 여러 플래그 조합해서 사용 가능)O_RDONLY
: 파일을 읽기 전용으로 열기O_WRONLY
: 파일을 쓰기 전용으로 열기O_RDWR
: 파일을 읽기와 쓰기가 가능하게 열기O_CREAT
: 파일이 없으면 파일을 생성O_EXCL
:O_CREAT
옵션과 함께 사용할 경우 기존에 없는 파일이면 파일을 생성하지만, 있는 경우 생성하지 않고 오류 출력O_APPEND
: 파일 맨 끝에 내용 추가O_TRUNC
: 파일을 생성할 때, 이미 존재하는 파일이고 쓰기 옵션으로 열린 경우 기존 내용을 모두 지움O_SYNC / O_DSYNC
: 저장장치에 쓰기가 끝나야 스기 동작을 완료
File Tabel
- 열린 파일을 관리하는 표
- kernel이 process별로 유지
- 열린 파일에 대한 각종 정보 관리
- (Access mode, file offset, pointer to files)
- [fd array] - [file table] - [filesystem]
mode
- 파일 권한 설정 값 사용
- 정의 된 플래그 사용
- 조합하여 사용 가능 (
|
OR bit operation) - 비트에 대한 해석으로 옵션을 유추할 수 있음
- 조합하여 사용 가능 (
S_IRWXU | 0700 | 소유자 읽기/쓰기/실행 권한 |
S_IRUSR | 0400 | 소유자 읽기 권한 |
S_IWUSR | 0200 | 소유자 쓰기 권한 |
S_IXUSR | 0100 | 소유자 실행 권한 |
S_IRWXG | 0070 | 그룹 읽기/쓰기/실행 권한 |
S_IRGRP | 0040 | 그룹 읽기 권한 |
S_IWGRP | 0020 | 그룹 쓰기 권한 |
S_IXGRP | 0010 | 그룹 실행 권한 |
S_IRWXO | 0007 | 기타 사용자 읽기/쓰기/실행 권한 |
S_IROTH | 0004 | 기타 사용자 읽기 권한 |
S_IWOTH | 0002 | 기타 사용자 쓰기 권한 |
S_IXOTH | 0001 | 기타 사용자 실행 권한 |
Closing Files - close (2)
1
2
3
#include <unistd.h>
int close (int fd);
- fd (file descriptor)
- return
- 0: success
- -1: error
[EX] Open & Close a file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
// ex1
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;
}
// ex2
int main(void){
int fd;
fd = open("hello.txt", O_CREAT|O_EXCL, 644);
if (fd==-1){ perror("EXCL"); exit(1); }
close(fd);
return 0;
}
Error handling for system call
- System call은 실패 시 -1을 반환
- Error code는 errno에 저장 됨
- error.h에 선언되어 있음 (special variable)
- extern으로 직접 접근 가능 (
extern
다른 파일에 정의된 변수에 접근)
- perror
- Error message를 출력해주는 함수
1
2
3
#include <stdio.h>
void perror(const char *str)
[EX] Allocating file desciptor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#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); // stdin 수정
fd = openFile();
printf("fd = %d\n", fd);
close(fd);
return 0;
}
2강-3. File read & write
Reading to a file - read (2)
1
2
3
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
- fd (file descriptor): 읽으려는 파일의 file desciptor
- buff (buffer): 읽은 내용을 저장할 buffer의 시작 주소
- count: 읽을 byte의 수
- return: 실제로 읽은 byte의 수
- 0: EOF
- -1: 에러
Writing to a file - write (2)
1
2
3
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
- fd (file descriptor): 기록하려는 파일의 file descriptor
- buf (buffer): 기록할 내용이 저장된 buffer의 시작 주소 (수정 방지를 위해
const
) - count: 기록할 byte의 수
- return: 실제로 기록한 byte의 수
- -1: 에러
File offset (File position)
- File operation (e.g., read/write)을 적용할 위치
- 파일의 시작점부터 현재 위치까지의 byte 수
- Read(2)/Write(2) 수행 시, 읽은/기록한 byte 수 만큼 순차적으로 이동
[EX] File Read & Write
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void){
int rfd, wfd, n;
char buf[10] = 0; // 버퍼 초기화
// 읽기용
rfd = open("hello.txt", O_RDONLY);
if (rfd==-1){ perror("Open hello.txt"); exit(1); }
// 쓰기용
wfd = open("hello.bak", O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (wfd==-1){ perror("Open hello.bak"); exit(1); }
// 복사
while ((n=read(rfd, buf, 6))>0) {
if (write(wfd, buf, n)!=n) { perror("Write"); }
}
if (n==-1) { perror("Read"); }
close(rfd);
close(wfd);
return 0;
}
File access methods
- Sequential access (순차 접근)
- File을 record(or bytes) 단위로 순서대로 접근
- Directed access (직접 접근)
- 원하는 Block(위치)을 직접 접근
- Indexed access
- Index를 참조하여, 원하는 block을 찾은 후 데이터에 접근
Moving the file offset = lseek (2)
1
2
3
4
5
#include <sys/types.h>
#include <unistd.h>
// Dicrected access
off_t lseek(int fd, off_t offset, int whence)
- fd (file descriptor): 대상 file descriptor
- offset: 이동 시킬 byte 수 (양수 or 음수)
- whence: 기준 위치
SEEK_SET
: 파일의 시작SEEK_CUR
: 현재 위치SEEK_END
: 파일의 끝
- return: 이동 후 file offset, -1 에러
cur_offset = lseek(fd, 0, SEEK_CUR)
[EX] Moving the file offset
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void){
int fd, n;
off_t start, cur;
char buf[256];
fd = open("linux.txt", O_RDONLY);
if (fd==-1) { perror("Open linux.txt"); exit(1); }
start = lseek(fd, 0, SEEK_CUR);
n = read(fd, buf, 255);
buf[n] = '\0'; // 문자열의 끝
printf("Offset start=%d, Read Str=%s, n=%d", (int)start, buf, n);
cur = lseek(fd, 0, SEEK_CUR); // cur == n
printf("Offset cur=%d\n", (int)cur);
start = lseek(fd, 6, SEEK_SET);
n = read(fd, buf, 255);
buf[n] = '\0';
printf("Offset start=%d, Read Str=%s", (int)start, buf);
close(fd);
return 0;
}
Page Cache & Write-Back
- Page cache
- In-memory sotre of recently accessed data from an on-disk filesystem
- Disk 접근 시간 절약을 위해 kernel 내부적 기법
- Page write-back
- Page cache에 변경 된 내용을 disk에 반영하는 것
- 반영 시기는 kernel이 결정
Synchronizing with disks - fsync (2)
1
2
3
#include <unistd.h>
int fsync(int fd);
- Page write-back을 강제로 수행
- fd (file descriptor): 대상 file descriptor
- return
- 0: success
- -1: error
2강-4. File descriptor 다루기
Duplcating FD - dup (2) / dup2 (2)
1
2
3
4
#include <unistd.h>
int dup(int oldfd);
int dup2(int oldfd, int newfd);
- oldfd (old file descriptor): 복사하려는 file descriptor
- newfd (new file descriptor)
- 새로운 fd 지정
dup()
의 경우 할당 가능한 fd 중 가장 작은 값 할당
- return: oldfd를 복사한 새로운 fd, -1 error
[EX] IO redirection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void){
int fd, fd1;
fd = open("tmp.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
if (fd==-1){ perror("Creat tmp.aaa"); exit(1); }
close(1); // stdout
fd1 = dup(fd);
printf("DUP FD=%d\n", fd1);
printf("Standard Output Redirection\n");
close(fd);
return 0;
}
Manipulating FD - fcntl (2)
1
2
3
4
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, /* arg */ ...);
- fd (file descriptor): 대상 file descriptor
- cmd (command): 수행할 명령
F_GETFL
: 상태 flag 읽기F_SETFL
: 상태 flag 설정 등
- arg (argument): cmd에 필요한 인자들
- return: cmd에 따라 다름
[EX] Changing FD flag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(void){
int fd, flags;
fd = open("linux.txt", O_RDWR);
if (fd==-1){ perror("open"); exit(1); }
if ((flags==fcntl(fd, F_GETFL))==-1){
perror("fcntl");
exit(1);
}
flags |= O_APPEND;
if (fcntl(fd, F_SETFL, flags)==-1){
perror("fcntl");
exit(1);
}
if (write(fd, "KOREATECH", 9)!=9) perror("write");
close(fd);
return 0;
}
Comments powered by Disqus.