3장 파일 시스템 (file system)
open() 시스템 호출: 파일 시스템에서 내가 원하는 파일을 쓴다고 커널에 요청하는 함수
close()
read()
write()
link()
unlink()
4장 파일(File)
디렉토리
- 파일 이름들의 저장소, 사용자로 하여금 임의의 파일들의 집합을 생성하여 저장
파일 시스템
- 디렉토리와 파일 시스템은 디스크의 물리적인 구획으로 구성하거나 전체 디스크에 구축
특수파일
- 파일 개념을 입출력 장치에 적용
홈 디렉토리(home directory)
- 사용자가 로그인할 때 최초로 접근하게 되는 디렉토리
- /etc/passwd 파일에 정의
디렉토리는 파일뿐만 아니라 다른 디렉토리(sub-directory)를 포함할 수 있다
- 루트 디렉토리(root-directory)
- 부 디렉토리(sub-directory)
fsck(1M)
-> 슈퍼블록이 정상적인지 아닌지 체크하는 명령어
mkfs(1M)
-> 파일시스템을 만드는 명령어
현재 작업 디렉토리(current working directory)
$ cd/usr/guest
- 현재 작업 디렉토리를 /usr/guest로 변경
- pwd 명령어 사용시 현재 작업 디렉토리의 경로이름 출력
- 현재 디렉토리가 /usr/guest 인 경우
$cat book/chap/(상대 경로명)과 $cat/usr/guest/book/chap/(절대 경로명)은 동일
유닉스 시스템은 디렉토리를 커널 내에서 보통 파일과 같은 방식으로 처리함
그러나 디렉토리가 파일과 다른 중요한 차이점은
디렉토리는 creat()나 open() 시스템 호출을 사용해서 생성할 수 없다
디렉토리와 관련된 전용 시스템 호출 집단을 사용한다
디렉토리 관련 정보의 관리는 디렉토리 항으로 구성
inode번호 하나의 파일이름 또는 부디렉토리 이름
inode 번호
디렉토리 이름이 길어지면서 디렉토리 내의 정보의 크기는 가변적으로 지정 가능
link()와 unlink() 시스템 호출
링크 카운트 값을 이용
유닉스에서 점(.) 과 이중점(..)은 모든 디렉토리에 항상 존재하는 디렉토리
유닉스 디렉토리 허가권
읽기 허가
- 디렉토리 내에 있는 파일이나 부 디렉토리으 ㅣ이름을 리스트 할 수 있다는 것을 의미
쓰기 허가
- 사용자가 디렉토리 내의 파일을 제거하거나 새로운 파일을 만들 수 있다는 것을 의미
실행 허가
- cd 명령 또는 children() 시스템 호출을 이용하여 디렉토리 내에 접근이 가능하다는 것을 의미
유닉스 디렉토리와 관련된 시스템 호출들은 별도로 제공
<direct.h>에 정의
디렉토리 생성 및 제거
유닉스 디렉토리는 mkdir() 시스템 호출을 이용하여 생성
#include <sys/types.h>
#include <sys/stat.h>
int mkidr(const char *pathname, mode_t mode);
유닉스에서 디렉토리를 삭제할 때 사용하는 시스템 호출은 rmdir()
#include<unistd.h>
int rmdir(const char *pathname);
- 디렉토리가 비어 있을 경우에만 성공
디렉토리 열기 및 닫기
#include <sys/types.h>
# include <dirent.h>
DIR * opendir(const char *dirname);
#include <dirent.h>
Int closedir(DIR * dirptr);
디렉토리가 opendir() 시스템 호출로 개방되면 각 디렉토리 항의 내용은 하나의 dirent구조체로 읽혀진다
#include <sys/type.h>
#include <dirent.h>
struct dirent *readdir (Dir *dirptr);
- readdir() 시스템 호출은 opendir() 시스템 호출로부터 유효한 디렉토리 스트림 포인터를 아규먼트로 전달받는다
처음 readdir() 시스템 호출에 의해 디렉토리 내의 첫 항이 struct dirent로 읽혀지고 첫번째 호출이 끝나면 디렉토리 포인터는 디렉토리 내의 다음 항으로 이동한다
dir = readdir() 시스템 호출
- 수행 후 읽혀지는 자료구조:
dir -> d_ino: inode 번호
dir -> d_name: 파일 이름 또는 디렉토리 이름
readdir() 시스템 호출
-> 처음에는 offset = 0으로 설정
-> 첫 번째 항을 dirent로 읽는다
-> offset = 0 + 첫번째 항의 길이
rewinddir() 시스템 호출
-> offset 값을 0으로 reset 하는 역할
#include <sys/types.h>
#include <dirent.h>
Void rewinddir(Dir *dirptr);
#include <unistd.h>
int chdir(const char *pathname);
path는 호출프로세스의 현재 작업 디렉토리가 되게 한다
- 한 프로그램이 주어진 디렉토리에서 많은 파일들을 접근할 필요가 있을 경우 유용
- UNIX "$ cd" 명령어 기능을 지원
디렉토리 및 파일들이 모여서 파일 시스템을 구성
시스템 관리자가 다루게 되는 기능
유닉스 파일 시스템
- 디렉토리 및 파일들이 모여서 파일 시스템을 구성
- 시스템 관리자가 다루게 되는 기능
유닉스파일 시스템에 포함된 정보는 유닉스 장치 파일(device file)에 의하여 1:1 연결
major number - device를 기능적으로 분류
minor number - 동일한 기능 debice 간에 구분할 때 사용
루트 파일 시스템
- 유닉스에서 가장 기본이 되는 파일시스템으로 항상 사용 가능하여야 하며 다른 파일시스템은 이 루트 파일시스템의 일부로써 연결(mount) 되어야만 사용
(1) VFS(Virtual File System) 파일 시스템
UNIX 커널 내의 다양한 파일시스템을 통합관리하는 가상의 파일시스템
다양한 실제 파일시스템을 통합관리
Vnode(Virtual node, Virtual inode)
- 유닉스 커널에서 하나의 파일을 나타내는 추상화한 자료 구조
- 커널 내의 inode 자료구조와 유사
블록0: 부트스트랩 블록
블록1: 수퍼 블록
블록2부터 n 까지: inode 블록들
블록 n+1부터 r까지: 자료 블록들
부트스트랩 로드(bootstrap loader)
시스템 부팅 시에 유닉스 커널 이미지를 주기억장치에 로드하기 위해 사용하는 부트 프로그램을 저장
suber block = 파일 시스템에 대한 모든 정보를 갖는다
- 파일시스템의 총 크기
- inode를 위해 준비된 블록 수
- 파일 시스템의 갱신된 날짜와 시간
- 가용 inode list
- 가용 block list
유닉스 장치 파일(device file)
장치파일(device file)
- 입출력장치는 파일 시스템 내의 파일 이름으로 접근
(1) 블록과 문자 장치 파일(block device file and character device file)
블록 장치(block device)
- 표준 크기 블록 단위로 장치와 커널 사이에 데이터 이동
문자 장치(character device)
- 문자 단위로 자료 전송
5장 프로세스 관리
1. 프로세스 관리 기본 개념
프로세스
- 수행중인 프로그램, 실행중인 프로그램
shell 인터프리터(interpreter)를 사용하여 명령어를 구동하기 위하여 새로운 프로세스를 하나 생성(fork)
어떠한 유닉스 프로세스도 여러 개의 다른 자식 프로세스(child process)들을 생성 가능
프로세스 트리의 꼭대기에는 init이라는 프로세스가 있음
유닉스에서 생성된 프로세를 보는 명령어 -$ ps -edf | more
init process
-> 모든 프로세스의 root가 되는 프로세스
-> init 프로세스가 종료되게 되면 시스템 shutdown 됨
-> daemon process
fork(): 호출 프로세스와 똑같은 새로운 프로세스를 하나 생성
exec(): 생성된 프로세스가 실행될 수 있도록 지원해주는 시스템 호출
wait(): 이 시스템 호출은 프로세스들 간에 기본적인 프로세스 동기화(synchronization) 기능을 제공
exit(): 프로세스를 종료시키는 시스템 호출(system call)
fork() system call
-> cpu 개수만큼 생성
-> cpu를 최대한 활용 가능
-> 컴퓨터 시스템 성능을 향상시킬 수 있다
-> 프로세스가 대기 상태 진입
exec() system call
-> 대기 상태 프로세스를 실행상태로 전환시켜주는 역할
-> cpu를 가진 상태
fork() 시스템 호출은 프로세스를 생성시키는 기본적인 프리미티브(primitive)
- 이 시스템 호출을 이용하여 다중 시스템(multtasking system)을 구현 가능
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
호출이 성공적으로 수행되면 커널은 호출하는 프로세스와 똑같은 복사본 프로세스를 생성
fork()가 호출된 후에는 자식 프로세스와 부모 프로세스가 동시에 수행
fork() 시스템을 호출하면 parent 프로세스에는 양의 정수가 리턴되고 child 프로세스에는 0이 호출되고 시스템 호출 실패시 -1이 리턴된다
exec() 시스템 호출은 인수가 전달되는 방법에 따라 다양한 형태의 exec() 시스템 호출을 제공
#include <unistd.h>
int execl(const char *path, const char *arg(), ..., const char *argn, (char *)0);
execl 시스템 호출은 NULL로 끝나는 부분이 인수로 주어진다
execl path 아규먼트는 수행해야 할 파일에 대한 경로 이름이 주어진다
int execlp(const char *file, const char *arg(), const char *argn, (char *)0);
execlp 시스템 호출은 수행가능 파일이름을 아규먼트로 주어진다
int execv(const char *path, char *const argv[]);
execv시스템 호출은 수행가능 파일이름과 인수의 배열이 아규먼트로 주어진다
int execvp(const char *path, char *const argv[]);
execvp 시스템 호출은 수행가능 파일이름이 아규먼트로 주어진다
exec()의 모든 변종들은 동일한 기능을 수행
모든 인수는 숫자형 포인터
첫번째 인수 path는 수행된 프로그램이 들어있는 파일의 이름
두번째 인수 이후는 프로그램 또는 명령의 이름 및 필요한 option
인수의 개수가 일정하지 않으므로 마지막을 알리는 NULL 포인터가 존재
exec() 시스템 호출과 fork() 시스템 호출을 이용한 프로세스의 실행
fork()로 자식 프로세스를 만들고 자식 프로세스 안에서 exec()를 이용하면 부 프로세스 내에서 새로운 프로그램을 수행할 수 있음
fork() 시스템 호출 실행 후 child 프로세스가 execl("/bin/ls", "ls", "-IR", (char *)0); 시스템 호출을 실행하는 경우
exec() 시스템 호출과 fork() 시스템 호출을 이용한 프로그램
parent 프로세스가 가지고 있는 자료구조는 child process에게 그대로 전송
-> parent 프로세스가 open한 파일의 정보는 child 프로세스에게 그대로 전달
-> parent 프로세스와 child 프로세스는 개방된 파일에 대해서 상호 참조를 하도록 되어 있다
-> parent 프로세스가 open된 파일을 사용할 경우 child 프로세스에게도 영향이 간다
-> p: 파일 읽기 100바이트 후 offset= 0 + 100 <--- child 프로세스도 이 값을 그대로 사용
부모 프로세스가 가지고 있는 변수 값들은 자식 프로세스에게 그대로 전달
부모 프로세스에서 개방된 파일은 자식 프로세스에게 개방되어 있다
fork()에 의해 양쪽으로 개방된 파일들은 부모와 자식 프로세스 간에 밀접하게 연관
자식 프로세스가 어떤 파일에서 파일 디스크립터의 포인터를 이동시키면 부모 프로세스에서도 이 파일의 파일 디스크립터 포인터가 이동
프로세스 종료
#include <stdlib.h>
void exit(int status);
프로세스와 관련한 개방된 파일을 닫는다
프로세스 동기화
#include <sys/types.h>
#include <sys/wait.h>
int wait(int *status);
자식 프로세스가 수행되고 있는 동안 부모 프로세스의 수행을 일시적으로 중단
자식 프로세스가 수행을 마치면 기다리던 부모 프로세스는 수행을 재개
좀비(Zombie) 프로세스의 처리
커널에서 프로세스와 관련한 테이블 자료를 할당받고 있는 상태로 프로세스가 수행이 되지 않는 상태이면서 커널의 자원을 사용하고 있다
1. 부모 프로세스가 수행하지 않고 있는 상태에서 자식이 퇴장
2. 하나 이상의 자식 프로세스가 수행되고 있는 상태에서 부모가 퇴장
1의 경우 부모가 wait를 수행하면 child 프로세스와 관련한 커널 내 자료들이 정리
2의 경우 부모는 정상적인 exit 절차를 밟고 자식들은 parent 프로세스로 init를 지정
프로세스 속성
프로세스 식별 번호
- 프로세스를 구별하는 유일한 번호
- 양의 정수
- process 0 -> swapperr process
- process 1 (PID) -> init process
자신의 프로세스 식별번호를 획득 가능
- pid = getpid();
부모 프로세스 식별번호 값을 획득 가능
- ppid = getppid();
back foreground
link count, link system call 장단점
directory 내의 정보를 저장하는 구조
정보를 읽어내는 system call read dir 의 동작원리 동작과정
file read write system 호출의 동작과정
눈에 보이지 않는 커널내의 offset값이 증가가 일어난다
이게 핵심포인트
프로그램은 시험에 안냄
directory의 permission, file permission과 다르다
system call에서 읽어들이는 자료구조 inode
init process zombie process
dot double dot 안나옴
root file system root directory 안나옴
fork exec 호출의 동작과정
fork 리턴되는 값
zombie process 설명