[회고] 신입 iOS 개발자가 되기까지 feat. 카카오 자세히보기

💻 CS/시스템프로그래밍

[시스템프로그래밍] Files and Directories

inu 2019. 11. 26. 23:33
반응형

이것은 한낱 대학생이 교수의 수업을 듣고 작성한 개인저장용 복습 문서입니다.

 

그렇지만, 물론 지적과 수정은 환영합니다.


Files and Directories

 

OS 는 물리적 디스크를 file systems으로 정리한다.
• File System
– 파일들과 위치나 이름같은 속성들의 모임 
디스크에서 파일의 물리적 위치를 지정하는 대신, 응용 프로그램은 filenameoffset을 지정한다.
• Directory
파일 이름을 Disk에 있는 파일의 실제 위치와 연결하는 directory entries를 포함하고 있는 파일.
• 대부분의 file systems은 tree structure로 구성되어 있다.

 


Directory

 

Root directory
– ‘/’
– file system tree의 꼭대기
– 그 외의 것들은 모두 이 아래에 있다


Parent directory
– “..”
– 현 디렉토리의 위에 존재하는 디렉토리


Current working directory
– “.”


Home directory
– 로그인을 했을 때 처음에 나타나는 디렉토리


Sub-directory
– 다른 디렉토리에 의해 포함되어진 디렉토리


절대경로 : /dirA/dirB/my1.dat (루트 디렉토리부터 차례대로)

상대경로 : ../dirC/my.dat (현 디렉토리에서)


Change Directory

 

#include 
int chdir(const char *path);

-path에 입력된 경로에 따라 디렉토리를 이동시킨다. 성공시 0 실패시 -1을 리턴한다.

-chdir 함수는 오직 현 프로세스의 working directory에만 작용한다.

1
2
3
4
5
6
#include <unistd.d>
int main (void) {
    char *directory = “/tmp”;
    if (chdir(directory) == -1)
        perror(“Failed to change current working directory to /tmp”);
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

Get Current Directory

 

#include 
char *getcwd(char *buf, size_t size);

 

-현재 디렉토리의 pathname을 리턴하는 함수

-buf : 현 디렉토리의 pathname을 담을 output파라미터

(버퍼는 pathname을 담을 수 있을 만큼 충분히 커야한다. -> PATH_MAX값 사용)

-size : pathname의 최대길이

-성공시 buf 리턴, 실패시 NULL 리턴

 

size값을 알아내는 방법

PATH_MAX : POSIX 자체적으로 정의된 값. pathname의 max값을 내포하고 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <limits.h>
#include <stdio.h>
#include <unistd.h>
#ifndef PATH_MAX
#define PATH_MAX 255
#endif
int main(void) {
    char mycwd[PATH_MAX];
    if (getcwd(mycwd, PATH_MAX) == NULL) {
        perror("Failed to get current working directory");
        return 1;
    }
    printf("Current working directory: %s\n", mycwd);
    return 0;
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

-ifndef : 만약 PATHMAX가 정의되어 있지 않으면 define으로 정의된 값 사용 endif로 마무리 


Search paths

 

-'PATH'라는 환경 변수 안에 OS가 탐색할 경로를 부여할 수 있다.

-실행을 위해 파일 이름만 지정되면 셸이 PATH 환경 변수에 의해 나열된 모든 가능한 디렉토리에서 실행 파일을 검색한다. (ex. ~~ 경로 ~~ /ls) 
-linux에서 PATH는 홈 디렉토리의 .profile 파일로 설정할 수 있다.
-"which" 프로그램은 해당 실행 파일의 전체 pathname을 가져오는 데 사용된다.
-PATH의 시작 부분에 "."를 넣는 것은 위험하다. ("."은 곧 현 디렉토리를 의미하기 때문에 타 사용자가 해당 시스템을 위협하기 쉬워진다.)


Directory Access

 

opendir, closedir, readdir 세가지로 directory를 open, close, read 가능.

 

(open)

#include <sys/types.h>
#include 
DIR *opendir (const char *dirname);

-DIR : directory entry의 주소가 들어 있다.

-즉, dir의 이름을 입력하면 해당 

-읽힌 directory는 알파벳순으로 정렬되어있지 않다.

 

(read)
#include <sys/types.h>
#include 
struct dirent *readdir (DIR *dirptr);

-read할 dir의 DIR값을 파라미터로 사용한다.

-struct dirent안에는 주로 directory의 이름이나 directory의 ino가 담겨있다.

-즉, ls의 간단한 구현도 가능하다.

 

(close)
#include

int closedir (DIR *dirptr);

 

(rewind)

#include <sys/types.h>
#include 
void *rewinddir (DIR *dirptr);

-포인터를 초기화한다.

-즉, 이 함수를 사용해 해당 DIR의 파일포인터를 초기화하고

-while(readdir(DIR *dirptr) != null)을 하면 해당 dir의 끝까지 탐색한다.

showname.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
 
int main(int argc, char *argv[]) {
    struct dirent *direntp;
    DIR *dirp;
    if (argc != 2) {
        fprintf(stderr, "Usage: %s directory_name\n"    , argv[0]);
        return 1;
    }
    if ((dirp = opendir(argv[1])) == NULL) {
        perror ("Failed to open directory");
        return 1;
    }
    while ((direntp = readdir(dirp)) != NULL)
        printf("%s\n", direntp->d_name);
    while ((closedir(dirp) == -1&&
        (errno == EINTR)) ;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

File status information

-lstat function에 링크를 주면 링크파일에 대한 값을 리턴하고
-stat function에 링크를 주면 원본에 대한 정보를 리턴한다.

 

#include <sys/stat.h>
int lstat(const char *restrict path, struct stat *restrict buf);
int stat(const char *restrict path, struct stat *restrict buf); 


struct stat structure

 

• Defined in sys/stat.h
• dev_t st_dev;
– Device ID of device containing file
• ino_t st_ino;
– inode 넘버 
• mode_t st_mode;
– 파일의 여러가지 타입 (regular, special, link, dir 등)
• nlink_t st_nlink;
– 하드링크의 개수 
• uid_t st_uid;
– 파일의 user id
• gid_t st_gid;
– 파일의 Group ID 
• off_t st_size;
– File size in bytes (regular files),
path size (symbolic link)
• time_t st_atime;
– Time of last access
• time_t st_mtime;
– Time of last data modification
• time_t st_ctime;
– Time of last file status change


printaccess.c

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
 
void printaccess(char *path) {
    struct stat statbuf;
    if (stat(path, &statbuf) == -1)
        perror("Failed to get file status");
    else
        printf("%s last accessed at %s", path, ctime(&statbuf.st_atime));
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

-last access time을 출력한다.

-stat함수로 원본파일에 대한 정보를 얻어 statbuf에 저장하고, statbuf에 담겨있는 st_atime정보를 통해 마지막 접속시간을 불러온다. 그리고 그를 ctime함수로 문자열로 바꿔준다.


Determining the type of a file

 

-struct stat의 멤버인 st_mode가 파일의 접근권한과 파일의 타입을 특정한다.

 

isdirectory.c : 해당 path의 파일이 directory인지 판별

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
int isdirectory(char *path) {
    struct stat statbuf;
    if (stat(path, &statbuf) == -1)
        return 0;
    else
    return S_ISDIR(statbuf.st_mode);
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

-statbuf의 st_mode를 검사

-S_ISDIR(m) : 디렉토리여부 판별

-S_ISREG(m) : 레귤러파일여부 판별

-S_ISCHR(m) : char여부 판별

-S_ISBLK(m) : block device 여부 판별

등등


dir ent -> inode -> status int -> file

여기서 inode는 고정된 크기를 가지며, 해당 값만 알면 모든 것을 알 수 있다.


Inode

 

-각 파일은 inode값을 가지고 있으며, 이는 inode number로 구분된다.

-data block을 찾아갈 수 있는 pointer값을 저장하고 있다.

-file의 상태정보를 가지고 있다. (ID 정보, access mode, type, 수정시간 ... )

-어떤 시스템이 가질 수 있는 inode의 갯수는 제한되어 있다.


전통적 UNIX파일의 구조

-맨 위는 status info (stat 구조체를 이루는 값들)

-그 밑은 pointer 정보 저장

-direct pointer 32KB

-single, double, triple : 하나, 둘, 세번의 단계를 거쳐서 파일을 확인. 

-여러 단계를 거쳐갈수록 파일이 포함할 수 있는 용량 증가 (32kb * 32kb * ... )


Directory 의 형태

 

directory : file name과 file location을 함께 가지고 있다. (inode number + file number)

 

참고로, pathname을 입력하면 경로 상 표현된 디렉토리를 쭉 따라간다.

그 후 dir ent를 확인하여, inode을 확인하는 것이다.


inode + filename의 장점

 

directory 안에서는 filename으로 관리하는데,

-파일 이름 변경시, directory entry까지만 가서 바로 변경가능

-다른 dir로 이동하는 과정도 dir ent만 변경해주면 되기 때문에 용이하다. (잘라내서 붙혀넣기가 빠른 이유)

-하나의 같은 파일을 가르키는 여러개의 파일이름을 가질 수 있다.

-dir ent는 매우 크기가 작다. 대부분은 inode에서 관리하기 때문이다.


Exercise (inode pointers)

 

inode가 128bytes라고 생각해보자. pointer는 4bytes이고 status infomation은 68bytes를 가진다.

block size는 8Kbytes이고 block pointers는 32bits이다.

 

inode에 direct pointer는 얼마나 존재하는가?
- single, double, triple indirect pointers가 각각 4 bytes씩 차지 (12 bytes)
- 128-68-12 = 48 bytes

- 48 / 4 = 12개


direct pointer로는 얼마나 큰 파일을 담을 수 있는가?
- 8K = 8 * 2^10 bytes
- 8192 * 12 = 98,304 bytes

- 12개의 direct file pointer 전부를 사용해도 96KB


single indirect pointers로는?
- 블락에서 각각 포인터가 32bits = 4byte를 가지므로, 블락에는 총 8KB / 4B = 2KB만큼의 추가 지정이 가능해진다.

- 따라서 2KB * 8KB = 16MB

double, triple?

- 2KB * 2KB * 8KB = 32GB

- 2KB * 2KB * 2KB * 8KB = 64TB


Hard Links and Symbolic Links

 

filename ---link---> inode

-일반적으로 hard link는 직접 연결된 관계

-Symbolic (Soft) link은 약하게 연결된 관계


Hard link

 

-inode 안에는 hard link의 갯수도 포함되어 있다. (즉, hard link라도 여러개일수 있다.)

-rm 혹은 unlink로 hard link를 지울 수 있고, hard link 숫자가 0이 되면 파일의 inode는 사라진다.

-여러개가 하나의 file에 연결된 경우, 하나만 바꿔줘도 file data가 바뀐다.

-동일한 file system안에 있는 파일끼리만 hard link가 가능하다.

 

#include 
int link (const char *path1, const char *path2);
int unlink (const char *path);

-path1은 소스경로, path2는 만들어질 경로

-ln /dirA/name1 /dirB/name2 와 같은 방식으로 하드링크 생성 가능

 

if (link(“/dirA/name1”, “/dirB/name2”) == -1)

    perror(“Failed to make a new link in /dirB”);

 


Symbolic link 

 

-다른 파일이나 디렉토리의 이름을 가지고 있는 특별한 타입의 파일

-간접적으로 원본의 path를 가지고 있는 것

-inode의 데이터블록에 다른 파일 혹은 디렉토리의 경로를 가지고 있다.

-OS 자체적으로 직접적인 파일을 찾을 때까지 탐색을 반복한다.

(symbolic link가 symbolic link를 가지면 계속 탐색)

- ln -s (target-path) (link_name-path) 로 연결가능 
- Symbolic links는 inode의 link count에 영향을 주지 않는다.

 

#include <unistd.h>

int symlink (const char *path1, const char *path2);

 

if (symlink(“/dirA/name1”, “/dirB/name2”) == -1)

    perror(“Failed to create symbolic link in /dirB”);

 

-$ ln -s /dirA/name1 /dirB/name2

반응형