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

💻 CS/시스템프로그래밍

[시스템프로그래밍] UNIX I/O - 2

inu 2019. 11. 7. 19:45

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

 

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


Opening

 

#include 
#include <sys/stat.h>
int open(const char *path, int flag);
int open(const char *path, int flag, mode_t mode);

 

-file offset : 입력 위치

-*path : 경로 / flag : 읽기or쓰기or읽기&쓰기 / mode : 파일을 새로만들시 해당 파일의 permission

-open의 리턴값인 파일의 정보는 file descriptor라고 한다. 

 

-flag : 액세스 모드 3가지 중 하나를 고르고, '|'를 사용해서 추가 옵션을 줄 수 있다.

ex) open("test.txt", O_RDWR | O_APPEND)

• 액세스 모드
– O_RDONLY: read only
– O_WRONLY: write only
– O_RDWR: read and write
• 추가 옵션 
– O_APPEND: file_offset이 전에 썼던 끝부분으로 이동한다. 
– O_TRUNC: 기존 파일의 내용을 초기화한다.
– O_CREAT: 새로 파일을 만들어서 그 파일을 열어주되, 파일이름이 겹치면 그냥 그 파일을 열어준다.
– O_EXCL: O_CREAT와 함께 사용, 파일이름이 겹칠 때 에러리턴해서 잘못된 파일 여는 것 방지.
– O_NOCTTY: prevents an opened device from becoming a controlling terminal

 

-현재 있는 파일의 덮어 쓸 위험을 피하려면? O_CREAT | O_EXCL 사용

 

Permission mask

 

user / group / else의 권한은 각각

read(r) write(w) execute(x)로 구성된다.  이에 대한 경우의 수는 총 2^3 = 8가지이다.

따라서 각 권한을 0~7로 표현할 수 있다.

0~7 / 0~7 / 0~7 로 표현가능. ex) 332, 755 등

O_CREAT 옵션 사용시 사용 (mode_t mode에)

 

POSIX 에서는 권한을 다른 방식으로 표기한다

이를 이용해

 

int fd;
mode_t fdmode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if ((fd = open(“info.dat”, O_RDWR | O_CREAT, fdmode)) == -1)
    perror(“failed to open info.dat”);

와 같이 mode_t mode 값을 초기화한다.

 

 


copyfilemain.c

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 <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#define READ_FLAGS O_RDONLY
#define WRITE_FLAGS (O_WRONLY | O_CREAT | O_EXCL)
#define WRITE_PERMS (S_IRUSR | S_IWUSR)
int main(int argc, char *argv[]) {
    int bytes;
    int fromfd, tofd;
    if (argc != 3) {
        fprintf(stderr, "Usage: %s from_fileto_file\n", argv[0]);
        return 1;
    }
    if ((fromfd = open(argv[1], READ_FLAGS)) == -1) {
        perror("Failed to open input file");
        return 1;
    }
    if ((tofd = open(argv[2], WRITE_FLAGS, WRITE_PERMS)) == -1){
        perror("Failed to create output file");
        return 1;
    }
    bytes = copyfile(fromfd, tofd);
    printf("%d bytes copied from %s to %s\n", bytes, argv[1],argv[2]);
    return 0/* the return closes the files*/
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

-인자가 3개가 아니면 오류  메세지 출력 (명령어 대상파일 목적파일)

-대상파일을 읽기전용로 열고, 목적파일을 새로만들고 덮어씌움방지를 하여 쓰기전용으로 연다.

-목적파일의 permission은 user에게 읽기와 쓰기권한만 준다.

-그리고 각 대상파일과 목적파일을 copyfile에 넣어준다. 


Closing

 

#include 
int close(int filedes);

 

사용이 끝난 open된 파일은 반드시 close해주어야한다.

프로세스가 아예 끝나면 프로세스에서 열린 파일은 자동으로 close된다.

r_close() : 시그널에 의한 에러 발생을 방지한 close함수

 

#include 
#include 
int r_close(int fd) {
    int retval;
    while (retval = close(fd), retval == -1 && errno == EINTR) ;
    return retval;
}


LSEEK

 

파일 offset의 위치를 임의로 이동시킨다.

 

#include<sys/types.h>
#include 
off_t lseek(int filedes,off_t offset,int start_flag);

 

-offset : off의 이동방향,크기 (-면 왼쪽, +면 오른쪽)

-flag : SEEK_SET 처음 / SEEK_CUR 현재 / SEEK_END 끝

 


File representation

 

File descriptors vs. pointers
• 파일은 file pointer혹은 file descriptor로  디자인된다.
• File pointers
– ISO C의 표준 I/O 라이브러리 함수에서 사용된다. (fopen, fscanf, fprintf, fread, fwrite, fclose..)
– stdin, stdout, stderr (defined in stdio.h)
• File descriptors
– UNIX I/O 함수에서 사용된다. (open, read, write, close, ioctl..)
– STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO (defined in unistd.h)


File descriptor 

-파일 하나를 열면, 프로세스에 특정된 File descriptor table의 한 부분을 차지한다.

-동시에 System file table, In-memory inode table도 한 부분씩 차지한다.

 

-System file table에는 오픈된 파일에 대한 정보가 들어있다 : file offset, access mode, count

-cf. count : 해당 위치를 지정하는 File descriptor table의 수 

-즉, 하나의 System file table에 여러개의 File descriptor table이 지정될 수 있다.

 

-In-memory inode table은 System file table이 가르킨다.

-System의 실제 파일에 대한 정보를 담고 있다 : meta info, status info의 레퍼런스

-즉, 파일의 inode를 가르킨다.

 

-만약 close를 통해 myfd를 닫으면, file descriptor talbe의 엔트리는 바로 삭제된다.

-하지만 system file table이나 in-memory inode talbe의 엔트리는 count값을 줄여준다.

-count값이 0이되면 해당 엔트리들도 삭제가 된다.

 

-만약 두개의 프로세스가 같은 파일을 시작해서 write를 한다면? 서로가 서로의 값을 덮어씌울 확률이 높다.

-만약 file offset이 inode table에서 관리된다면? 덮어씌울일없이 서로 공유하여 하나씩 입력이 가능하다.


File Pointers

 

-FILE 이라는 data structure를 가르키는 포인터 

-FILE : buffer + file descriptor value

-fprintf , fwrite? 바로 읽거나 쓰지 않고, buffer에 쓰여지다가 buffer가 가득차면 읽고 쓴다.

-만약 buffer가 딜레이되면 fflush를 통해 버퍼를 강제로 비워서 사용할 수 있다.

-terminal환경에서는 line-buffered, 즉 라인이 차면 출력을 실행한다.

-단, STD-ER은 제외. 에러메세지와 같이 우선순위가 높은 것은 STD-ER로 바로 출력된다.


-open 후 fork 시 부모의 file descriptor 정보가 상속되기 때문에 같은 System file table을 가리키게 된다. (a, b)

-하지만 fork 후 open 시 각각 다른 file descriptor 정보를 가지고 있어 다른 System file talbe을 가리키게 된다. (a, a)


-개행 문자 \n이 없는 경우 buffer를 물려주어, "This is my output.This is my output." 두 번 출력. file offset도 그 뒤에

-개행 문자 \n이 있는 경우 buffer를 물려주지않아, "This is my output." 한번 출력. file offset 한라인 아래에