Unix 의 역사 Bell Lab의 Ken Tompson이 PDP-7 위에서 개발 (1969년) Dennis Ritchie가 참가하여 대부분을 C언어로 작성 Sixth Edition 개발 (1976년) 다른 기관이 사용할 수 있도록 배포한 최초의 버전 이후에 UNIX는



Similar documents
Microsoft PowerPoint - chap3 [호환 모드]

Microsoft PowerPoint APUE(Files and Directories).ppt

Discrete Mathematics

chap7.key

슬라이드 1

Microsoft PowerPoint APUE(File InO).ppt

Microsoft PowerPoint APUE(File InO)

제1장 Unix란 무엇인가?

Microsoft PowerPoint APUE(File InO).pptx

Microsoft PowerPoint - chap2

10.

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

Microsoft PowerPoint - chap4 [호환 모드]

제1장 Unix란 무엇인가?

Microsoft PowerPoint - 09_FileSystem

歯9장.PDF

제12장 파일 입출력

PowerPoint 프레젠테이션

<4D F736F F F696E74202D FC6C4C0CFB0FA20B5F0B7BAC5E4B8AE205BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint APUE(Intro).ppt

제1장 Unix란 무엇인가?


로봇SW교육원 강의자료

Microsoft PowerPoint - chap12 [호환 모드]

로봇SW교육원 강의자료

6주차.key

<4D F736F F F696E74202D FC6C4C0CF20C0D4C3E2B7C2205BC8A3C8AF20B8F0B5E55D>

로봇SW교육원 강의자료

2009년 상반기 사업계획

학번 : 이름 : 1. 다음파일트리구조를가진유닉스시스템이있다고가정하자. / /bin/ /home/ /home/taesoo/ /usr/ /usr/lib/ /usr/local/lib /media 모든폴더에파일이하나도없다고가정했을때사용자가터미널에서다음 ls 명령입력시화면출력

금오공대 컴퓨터공학전공 강의자료

Microsoft PowerPoint - Lecture 4-1 Linux File Environment.ppt [호환 모드]

제1장 Unix란 무엇인가?

PowerPoint 프레젠테이션

Microsoft PowerPoint - 제11강 파일 처리

PowerPoint 프레젠테이션

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

K&R2 Reference Manual 번역본

PowerPoint 프레젠테이션

프로그램을 학교 등지에서 조금이라도 배운 사람들을 위한 프로그래밍 노트 입니다. 저 역시 그 사람들 중 하나 입니다. 중고등학교 시절 학교 도서관, 새로 생긴 시립 도서관 등을 다니며 책을 보 고 정리하며 어느정도 독학으르 공부하긴 했지만, 자주 안하다 보면 금방 잊어

Chap06(Interprocess Communication).PDF

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

untitled

슬라이드 1

PowerPoint Template

학번 : 이름 : 1. 다음파일트리구조를가진유닉스시스템이있다. / /bin/ /home/ /home/taesoo/ /home/taesoo/downloads /usr/ /usr/lib/ /usr/local/lib /media 모든폴더에파일이하나도없다고가정했을때사용자 (t

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션

Adobe Flash 취약점 분석 (CVE )

BMP 파일 처리

고급 프로그래밍 설계

<4D F736F F F696E74202D2034C5D8BDBAC6AEC6C4C0CFC0D4C3E2B7C2312E505054>

<4D F736F F F696E74202D FB8DEB8F0B8AE20B8C5C7CE205BC8A3C8AF20B8F0B5E55D>

Microsoft PowerPoint - ch09_파이프 [호환 모드]

2009년 상반기 사업계획

휠세미나3 ver0.4

2009년 상반기 사업계획

PowerPoint 프레젠테이션

Microsoft PowerPoint - chap1 [호환 모드]

3. 다음그림은프로세스의 file table 과 v-node 테이블의연결관계예제이다. 위그림을참고하여두개의서로다른프로세스가같은파일을 open 명령을사용하여열었을때의연결관계를도시하시오. 4. 메모리영역은 low-address 부터 high-adress 까지순서대로나열했을

À©µµ³×Æ®¿÷ÇÁ·Î±×·¡¹Ö4Àå_ÃÖÁ¾

C Programming

Microsoft PowerPoint - chap6 [호환 모드]

API 매뉴얼

13주-14주proc.PDF

Chapter #01 Subject

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

Computer Programming (2008 Fall)

제7장 C 표준 파일 입출력

Microsoft PowerPoint - 09_(C_Programming)_(Korean)_File_Processing

Microsoft Word - Network Programming_NewVersion_01_.docx

Microsoft PowerPoint - 알고리즘_4주차_1차시.pptx

Microsoft PowerPoint - 09-Pipe

ABC 11장

금오공대 컴퓨터공학전공 강의자료

PowerPoint 프레젠테이션

The Pocket Guide to TCP/IP Sockets: C Version

PowerPoint 프레젠테이션

제7장 C 표준 파일 입출력

Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3

PowerPoint 프레젠테이션

강의10

슬라이드 1

Sena Technologies, Inc. HelloDevice Super 1.1.0

컴파일러

Microsoft PowerPoint - chap10-함수의활용.pptx

SRC PLUS 제어기 MANUAL

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

PowerPoint 프레젠테이션

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D D382E687770>

Microsoft PowerPoint - a10.ppt [호환 모드]

The Pocket Guide to TCP/IP Sockets: C Version

1217 WebTrafMon II

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

ActFax 4.31 Local Privilege Escalation Exploit

Microsoft PowerPoint - 10_C_Language_Text_Files

Microsoft PowerPoint - [2009] 02.pptx

, ( ),, ( ), 3, int kor[5]; int eng[5]; int Microsoft Windows 4 (ANSI C2 ) int kor[5] 20 # define #define SIZE 20 int a[10]; char c[10]; float

/chroot/lib/ /chroot/etc/

Transcription:

고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 제1장 소개 2004. 08. 22 1

Unix 의 역사 Bell Lab의 Ken Tompson이 PDP-7 위에서 개발 (1969년) Dennis Ritchie가 참가하여 대부분을 C언어로 작성 Sixth Edition 개발 (1976년) 다른 기관이 사용할 수 있도록 배포한 최초의 버전 이후에 UNIX는 크게 분류해서 연구용, AT&T 계열, BSD 계열로 분 화해서 발전 Seventh Edition (1979년): Bourne shell 개발 Eighth Edition (1985년): STREAMS 개발 2

AT&T UNIX System V, Release 3 개발 (1987년) : STREAMS 도입 System V, Release 4 개발 (1989년) : C/Korn shell, Job control, Symbolic link BSD UNIX BSD 4 개발 (1980년) : Job control, Reliable signal BSD 4.4 개발 (1993년) 기타 Mach Linux 3

Unix 표준화 동향 ANSI C (1989년) American National Standards Institute C 언어의 문법, 라이브러리와 헤더 파일의 표준을 제정 다양한 운영 체제 환경에서 C 프로그램의 호환성을 높이기 위함 POSIX (1988년) Portable Operating System Interface for Computer Environments 운영 체제가 제공해 주어야 하는 서비스를 정의 (POSIX Compliant) 1003.1 : 운영 체제의 인터페이스 표준 (POSIX.1 이라고도 함) 1003.2, 1003.7 등 XPG3 (1989년) X/Open Portability Guide 4

시스템 호출과 라이브러리 함수 System Calls well defined entry points directly into the kernel documented in section 2 of the UNIX man pages look like C functions which can be called from a user's program just need to include the appropriate header Library Functions the library function is often more elaborate than the system call, and usually invokes the system call 5

application code user process C library functions system calls kernel kernel hardware (harddisk ) 6

Error Handling #include <errno.h> extern int errno; UNIX 시스템 호출에서 에러가 발생하면 에러 발생을 의미하는 값이 리턴되고 (-1 or NULL) 전역 변수 errno 에 자세한 에러 상수 값이 설정 된다 errno 에 설정될 수 있는 에러 상수 값은 <errno.h> 에 정의되어 있다 7

#include <string.h> char *strerror(int errno); 파라미터 errno 값에 해당하는 에러 메시지를 리턴 #include <stdio.h> void perror(const char *msg); 표준 에러에 다음과 같은 순서로 메시지를 출력한다 msg 출력 문자열 ": " 출력 전역 변수 errno 값에 해당하는 에러 메시지 출력 8

고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 2장. 파일 입출력 (File I/O) 2004. 08. 22 1

Contents I/O를 위한 kernel 자료구조 open() - 열기 creat() - 파일 생성 close() - 닫기 read() - 읽기 write() - 쓰기 lseek() - 이동 I/O Efficiency I/O 시스템 호출과 커널 자료구조 dup(), dup2() fcntl() Atomic operations 2

1. I/O를 위한 kernel 자료구조 process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2: fd 3:.... file table fd status flags current file offset v-node ptr fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size v-node information i-node information current file size 3

Process table entry 프로세스 테이블 (process table) 커널(kernel) 자료구조 프로세스 목록 프로세스 à 프로세스 테이블 항목 프로세스 테이블 항목 (Process table entry) 파일 디스크립터(file descriptor)의 배열을 포함 4

File descriptor 읽거나 쓰기 위해서 파일을 열면 (open 시스템 호출) 파일 디스크립터(file descriptor) 배열의 항목이 하나 할당되고 그 파일 디스크립터가 리턴된다 (배열의 인덱스가 리턴됨) 이후 이 파일에 대한 읽기/쓰기 시스템 호출(system call)에서는 이 파일 디스크립터를 파라미터로 전달해야 한다 파일 디스크립터 배열의 크기가 유한하므로 프로세스가 동시에 열 수 있는 파일의 수도 유한하다 파일 테이블 항목(file table entry)에 대한 포인터를 파일 디스크립 터는 가지고 있다. 5

File table entry 파일 테이블 (file table) 커널 자료구조 열려진 모든 파일 목록 열려진 파일 à 파일 테이블의 항목 파일 테이블 항목 (file table entry) 파일 상태 플래그 (read, write, append, sync, nonblocking, ) 파일의 현재 위치 (current file offset) v-node에 대한 포인터 6

v-node v-node의 내부 파일의 유형 함수들에 대한 포인터 배열 이 파일을 다루는데 사용되는 함수들 i-node 하드 디스크에 저장되어 있는 자료구조 파일에 대한 정보를 가지고 있음 소유자, 크기 파일이 위치한 장치 파일 내용 디스크 블럭에 대한 포인터 7

2. open() - 열기 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open (const char *pathname, int oflag, [ mode_t mode ]); 파일을 연다 파일이 없으면 경우에 따라 새로 만들어 질 수도 있다 리턴 값 : 파일 디스크립터(file descriptor), 실패하면 -1 pathname : 파일의 이름 mode : 파일의 access permission 값. 생략가능. 새로운 파일을 만드는 경우에만 사용됨 creat() 함수 설명 참조 8

open() 의 파라미터 두 번째 파라미터 oflag는 다음 상수들의 OR 이다 예) int fd; fd = open("afile", O_RDWR O_CREAT, S_IRUSR S_IWUSR ); 반드시 하나 지정해주어야 할 값 O_RDONLY : 읽기 모드, write 함수를 사용 할 수 없음 O_WRONLY : 쓰기 모드, read 함수를 사용 할 수 없음 O_RDWR : 읽고 쓰기 모드, read write 사용 가능 9

open() 의 파라미터 선택적 지정 가능 O_APPEND : 모든 write 된 데이터는 파일의 끝에 추가된다 O_CREAT : 파일이 없을 경우 파일을 생성한다 이때에만 세번째 인자 mode 가 필요하다 O_EXCL : 그 이름의 파일이 이미 있고 O_CREATE 를 지정한 경우 에러를 발생시킨다 O_TRUNC : 파일이 있는 경우에 기존 내용을 지우고 파일 크기를 0으로 만든다 O_NONBLOCK : nonblocking 모드로 입출력을 함 O_SYNC : 각 write 함수 호출은 디스크에 물리적으로 쓰여진 후 리턴한다 10

/* open.c */ #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include "error.h" int main() { int filedes; char fname[] = "afile"; if ((filedes = open (fname, O_RDWR)) == -1) error(fname); } printf("%s is opened.\n", fname); close(filedes); return 0; 11

3. creat () - 파일 생성 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int creat ( const char *pathname, mode_t mode ); 새로운 파일을 생성한다 리턴 값 : 파일 디스크립터, 실패하면 -1 pathname : 생성하고자 하는 파일의 이름 mode : 파일의 access permission 값 12

creat () 의 파라미터 다음의 두 함수 호출은 기능이 동일하다 fd = creat ( pathname, mode ); fd = open ( pathname, O_WRONLY O_CREAT O_TRUNC, mode); 두 번째 인자 mode는 다음 상수들의 OR 이다 S_IRUSR : user-read, 소유자의 읽기 허용 S_IWUSR : user-write, 소유자의 쓰기 허용 S_IXUSR : user-execute, 소유자의 실행 허용 S_IRGRP : group-read, 그룹 멤버의 읽기 허용 S_IWGRP : group-write, 그룹 멤버의 쓰기 허용 S_IXGRP : group-execute,그룹 멤버의 실행 허용 S_IROTH : other-read, 아무나 읽기 허용 S_IWOTH : other-write, 아무나 쓰기 허용 S_IXOTH : other-execute,아무나 실행 허용 13

4. close () - 닫기 #include <unistd.h> int close ( int filedes ); 작업이 끝난 후 파일을 닫는다. 리턴 값 : 성공하면 0, 실패하면 -1 filedes : 닫고자 하는 파일의 파일 디스크립터 파일을 닫지 않더라도 프로세스가 종료하면 모든 열려진 화일들은 자 동적으로 닫힌다 14

5. read () - 읽기 #include <unistd.h> ssize_t read ( int filedes, void *buf, size_t nbytes ); 파일에서 데이터를 읽는다 리턴 값: 성공하면 읽은 바이트 수 파일의 끝을 만나면 0 실패하면 -1 buff : 읽은 데이터를 저장할 메모리 nbytes : 메모리의 크기 15

read () - 읽기 읽을 데이터가 충분하면 한 번에 nbytes 만큼 읽는다. 읽을 데이터가 nbytes 보다 적은 경우 더 적게 읽기도 한다 파일의 끝에서 네트웍 입출력에서 size_t : unsigned integer ssize_t : signed integer 16

/* count.c -- 파일의 문자 수를 센다 */ #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include "error.h" #define BUFSIZE 512 int main() { char buffer[bufsize]; int filedes; ssize_t nread; long total = 0; if ((filedes = open("afile", O_RDONLY)) == -1) error("afile"); /* 파일의 끝에 도달할 때까지 반복 */ while( (nread = read(filedes, buffer, BUFSIZE)) > 0) total += nread; } close(filedes); printf ("total chars in afile: %ld\n", total); return 0; 17

6. write() - 쓰기 #include <unistd.h> ssize_t write (int filedes, const void *buf, size_t nbytes); 파일에 데이터를 쓴다 리턴 값 성공하면, 파일에 쓰여진 데이터의 바이트 수 실패하면, -1 buff : 쓸 데이터를 저장하고 있는 메모리 공간 nbytes : 쓸 데이터의 바이트의 수 18

/* copyfile.c -- 파일을 복사한다 */ #include <unistd.h> #include <fcntl.h> #define BUFSIZE 512 #define PERM 0644 int copyfile (const char *srcfile, const char *destfile) { int infile, outfile; ssize_t nread; char buffer[bufsize]; } if ((infile = open(srcfile, O_RDONLY)) == -1) return -1; if ((outfile = open(destfile, O_WRONLY O_CREAT O_TRUNC, PERM)) == -1) { close(infile); return -2; } while ((nread = read(infile, buffer, BUFSIZE)) > 0) { if (write(outfile, buffer, nread) < nread) { close (infile); close (outfile); return -3; } } close (infile); close (outfile); if (nread == -1) return -4; /* 마지막 읽기에서 에러 발생 */ return 0; 19

7. lseek() - 이동 #include <sys/types.h> #include <unistd.h> off_t lseek (int filedes, off_t offset, int whence ); 파일의 현재 위치(current file offset)를 이동 리턴 값: 성공하면 현재 위치를 리턴, 실패하면 -1 whence : 위치 기준점 SEEK_SET : 파일의 시작점을 기준으로 이동 SEEK_CUR : 현재 위치를 기준으로 이동 SEEK_END : 파일의 끝을 기준으로 이동 offset : 기준점에서의 상대적인 거리 (byte 단위) SEEK_CUR, SEEK_END 와 같이 쓰일 때는 음수도 가능 20

lseek() 이동 파일의 현재 위치를 임의의 위치로 이동한다 파일의 현재 위치(current file offset) 파일에 대한 읽기/쓰기는 파일의 현재 위치에서 실행된다 파일을 처음 열면 현재 위치는 0 즉 파일의 시작이다 읽기/쓰기 후 파일의 현재 위치는 읽기/쓰기 한 byte 수 만큼 저 절로 뒤로 이동된다 lseek()를 사용하여 임의의 위치로 파일의 현재 위치를 이동할 수 있다 21

/* lseek.c */ #include <unistd.h> int main() { if (lseek(stdin_fileno, 0, SEEK_CUR) == -1) printf("cannot seek\n"); else printf("seek OK\n"); return 0; } 22

#include <unistd.h> /* lseek1.c */ #include <fcntl.h> #include "error.h" char char buf1[] = "abcdefghij"; buf2[] = "ABCDEFGHIJ"; int main() { int fd; } if ( (fd = creat("file.hole", S_IRUSR S_IWUSR S_IRGRP S_IROTH)) < 0) error("file.hole"); if (write(fd, buf1, 10)!= 10) /* offset now = 10 */ error("buf1"); if (lseek(fd, 40, SEEK_SET) == -1) /* offset now = 40 */ error("lseek"); if (write(fd, buf2, 10)!= 10) /* offset now = 50 */ error("buf2"); return 0; 23

lseek1.c 의 출력 파일 file.hole의 내용 0 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j 10 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 20 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 30 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 40 A B C D E F G H I J 24

#include <sys/types.h> /* lseek2.c */ #include <unistd.h> #include <fcntl.h> #include "error.h" int main() { int fd; off_t fsize; char buf[11]; } if((fd=open("file.hole", O_RDONLY)) < 0) error("file.hole"); fsize = lseek(fd, 0, SEEK_END); printf("size: %lu\n", fsize); lseek(fd, 40, SEEK_SET); read(fd, buf, 10); buf[10] = 0; puts(buf); return 0; 25

8. I/O Efficiency 디스크는 메모리에 비해서 상대적으로 매우 느린 장치 성능을 위해서는 디스크 I/O의 횟수를 줄이는 것이 바람직 작은 양을 여러번 I/O 하는 것 보다 많은 양을 I/O 하여 횟수를 줄이는 것이 좋다 write1.c 에서 BUFFSIZE 값을 변경하며 수행 시간을 측정 8192 까지는 BUFFSIZE 가 클수록 성능이 향상 8192 보다 큰 경우는 성능에 변화가 없다 26

Berkeley fast filesystem 의 I/O 단위는 8192 BUFFSIZE 가 8192 보다 큰 경우 내부 I/O 의 단위는 8192 이므로 성능의 향상이 없다 BUFFSIZE 가 8192의 배수가 아닌 경우는 오히려 8192 인 경우보다 I/O 횟수가 많아져 성능이 하락할 수 있다 27

#include <sys/types.h> /* write1.c */ #include <sys/stat.h> #include <fcntl.h> #include "error.h" #define BUFFSIZE 512 #define FILESIZE (100 * 1024 * 1024) #define COUNT FILESIZE / BUFFSIZE int main() { int i, fd; char buf[buffsize]; } memset(buf, '.', BUFFSIZE); if ((fd = creat("file.write", S_IRUSR S_IWUSR)) < 0) error("file.write"); for (i=0; i < COUNT; ++i) write(fd, buf, BUFFSIZE); close(fd); return 0; 28

BUFFSIZE User CPU (seconds) System CPU (seconds) Clock time (seconds) #loops 1 140.9 1,378.1 1,527.8 104,857,600 2 73.3 681.1 764.5 52,428,800 4 31.6 343.9 379.6 26,214,400 8 16.6 172.3 191.5 13,107,200 16 8.5 86.7 98.1 6,553,600 32 3.9 45.1 51.6 3,276,800 64 2.0 23.5 28.1 1,638,400 128 1.1 12.8 16.3 819,200 256 0.5 7.4 10.4 409,600 512 0.3 4.9 7.9 204,800 1,024 0.1 2.9 6.0 102,400 2,048 0.0 2.0 4.7 51,200 4,096 0.0 1.6 4.2 25,600 8,192 0.0 1.1 3.6 12,800 16,384 0.0 1.1 3.6 6,400 32,768 0.0 1.1 3.6 3,200 65,536 0.0 1.1 3.6 1,600 131,072 0.0 1.1 3.6 800 29

9. I/O 시스템 호출과 커널 자료구조 process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2: fd 3:.... file table fd status flags current file offset v-node ptr fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size v-node information i-node information current file size 30

read / write 시스템 호출 file table entry 의 current file offset 값이 읽은/쓰여진 바이 트 수 만큼 증가 write 후 file table entry의 current file offset 이 i-node의 current file size 보다 크면 current file size 값이 증가 파일이 O_APPEND 플래그로 오픈되었으면 file table entry의 file status flags 에 해당 플래그가 세팅됨 모든 write 시스템 호출은 먼저 current file offset을 i-node 의 current file size 값 으로 설정한 후 수행된다 따라서 모든 write 는 파일의 끝에 덧붙여진다 31

lseek 시스템 호출은 file table entry 의 current file offset 값을 변경 disk I/O 는 없음 lseek에서 SEEK_END 를 사용하여 파일의 끝으로 이동하면 file table entry 의 current file offset 값은 i-node 의 current file size 값으로 설정됨 32

10. dup(), dup2() #include <unistd.h> int dup (int filedes); int dup2 (int filedes, int filedes2); 사용 중인 파일 디스크립터의 복사본을 만듦 dup() 는 새 파일 디스크립터 번호가 할당됨 dup2() 는 filedes2 를 사용 filedes2 가 이미 사용 중이면 먼저 close 한다 리턴 값: 성공하면 복사된 새 파일 디스크립터, 실패하면 -1 dup() 함수는 할당 가능한 가장 작은 번호를 리턴한다. dup2() 함수는 filedes2 를 리턴한다. 33

파일 공유 1 process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2: fd 3:.... file table fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size newfd = dup(1); or newfd = dup2(1,3); 호출 후 리턴 값은 3 file table 의 current file offset 와 fd status flags 는 공유됨 file descriptors의 fd flags 는 공유안됨 34

#include <fcntl.h> /* dup.c */ #include <unistd.h> #include "error.h" int main() { int fd1, fd2, n; char buf[11]; } if ((fd1 = open("afile", O_RDONLY)) < 0) error("afile"); if ((fd2 = dup(fd1)) < 0) error("dup"); n = read(fd1, buf, 10); buf[n] = 0; puts(buf); n = read(fd2, buf, 10); buf[n] = 0; puts(buf); close(fd1); close(fd2); return 0; 35

파일 공유 2 process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2: fd 3:.... file table fd status flags current file offset v-node ptr fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size 같은 파일에 대하여 open() 을 두번 호출한 경우 current file offset 은 공유되지 않는다 36

#include <fcntl.h> /* open2.c */ #include <unistd.h> int main() { int fd1, fd2, n; char buf[11]; fd1 = open("afile", O_RDONLY); fd2 = open("afile", O_RDONLY); if (fd1 < 0 fd2 < 0) error("afile"); } n = read(fd1, buf, 10); buf[n] = 0; puts(buf); n = read(fd2, buf, 10); buf[n] = 0; puts(buf); close(fd1); close(fd2); return 0; 37

파일 공유 3 process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2:.... file descriptors fd 0: fd flags ptr fd 1: fd 2:.... file table fd status flags current file offset v-node ptr fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size 두 프로세스(process)에서 같은 파일을 연 경우 38

dup(), dup2() 의 용도 표준 입출력의 redirection 표준 입출력 대상을 파일로 바꿈 표준 입출력의 파일 디스크립터 #include <unistd.h> #define STDIN_FILENO 0 /* 표준 입력 */ #define STDOUT_FILENO 1 /* 표준 출력 */ #define STDERR_FILENO 2 /* 표준 에러 */ 39

#include <unistd.h> /* dup1.c */ #include <fcntl.h> #include <stdio.h> int main() { int fd; } if((fd = creat("afile", S_IRUSR S_IWUSR)) == -1) error("afile"); printf("this is displayed on the screen.\n"); dup2(fd, STDOUT_FILENO); printf("this is written into the redirected file.\n"); return 0; 40

#include <unistd.h> /* dup2.c */ #include <fcntl.h> #include <stdio.h> #include "error.h" int main() { int fd; } if((fd = creat("afile", S_IRUSR S_IWUSR)) == -1) error("afile"); printf("this is displayed on the screen.\n"); close(stdout_fileno); dup(fd); printf("this is written into the redirected file.\n"); return 0; 41

11. fcntl() #include <sys/types.h> #include <fcntl.h> #include <unistd.h> int fcntl (int filedes, int cmd, /* int arg */ ); 열려져 있는 파일의 속성을 알아내거나 속성을 변경한다. 리턴 값: cmd 값에 따라 다름, 실패하면 -1 42

fcntl() 의 두번째 파라미터 F_DUPFD 파일 디스크립터를 복사 dup() dup2() 와 유사함 세 번째 인수 보다 크거나 같은 값 중, 가장 작은 미사용의 값을 리턴 F_GETFD : file descriptor의 file descriptor flags 를 리턴 F_SETFD : file descriptor flags 를 설정 F_GETFL : file table 의 file status flags 를 리턴 F_SETFL : file status flags 를 설정 43

file table 의 file status flags File status flag O_RDONLY O_WRONLY O_RDWR O_APPEND O_NONBLOCK O_SYNC O_ASYNC Description open for reading only open for writing only open for reading and writing append on each write nonblocking mode wait for writes to complete asynchoronouse I/O (4.3 BSD only) F_SETFL 는 O_APPEND O_NONBLOCK O_SYNC O_ASYNC 만을 설정할 수 있음 44

F_GETOWN asynchronous I/O ownership 을 리턴 SIGIO, SIGURG 시그널을 받는 프로세스 ID를 리턴 F_SETOWN asynchronous I/O ownership 을 설정 SIGIO, SIGURG 시그널을 받는 프로세스 ID를 설정 45

#include <sys/types.h> /* fileflags.c */ #include <fcntl.h> #include "error.h" int main() { int accmode, val; int fd; fd = open("afile", O_WRONLY O_APPEND); if (fd == -1) error("afile"); if ((val = fcntl(fd, F_GETFL, 0)) < 0) error("fcntl"); accmode = val & O_ACCMODE; if (accmode == O_RDONLY) printf("read only"); else if (accmode == O_WRONLY) printf("write only"); else if (accmode == O_RDWR) printf("read write"); else printf("unknown access mode"); } if (val & O_APPEND) printf(", append"); if (val & O_NONBLOCK) printf(", nonblocking"); if (val & O_SYNC) printf(", synchronous writes"); putchar('\n'); return 0; 46

Asynchronous Write UNIX 에서 write 는 asynchronous write 이다 데이터가 디스크에 쓰여지길 기다리지 않고 쓰여질 데이터를 큐(queue)에 등록하고 바로 리턴한다 큐에 등록된 데이터는 나중에 디스크에 쓰여진다 synchronous write write 호출은 데이터가 실제로 디스크에 쓰여진 후 리턴한다 asynchronous write에 비해서 clock time 이 증가한다 file table 의 file status flags 에서 O_SYNC 플래그를 설정 47

#include <sys/types.h> /* write2.c */ #include <sys/stat.h> #include <fcntl.h> #include "error.h" #define BUFFSIZE 8192 #define FILESIZE (100 * 1024 * 1024) #define COUNT FILESIZE / BUFFSIZE void set_fl(int fd, int flags) /* flags are file status flags to turn on */ { int val; } if ( (val = fcntl(fd, F_GETFL, 0)) < 0) error("fcntl F_GETFL error"); val = flags; /* turn on flags */ if (fcntl(fd, F_SETFL, val) < 0) error("fcntl F_SETFL error"); 48

int main() { int i, fd; char buf[buffsize]; } memset(buf, '.', BUFFSIZE); if ((fd = creat("file.write", S_IRUSR S_IWUSR)) < 0) error("creat erroror"); set_fl(fd, O_SYNC); /* turn on the synchronous-write flag */ for (i=0; i < COUNT; ++i) write(fd, buf, BUFFSIZE); close(fd); return 0; 49

BUFFSIZE User CPU (seconds) System CPU (seconds) Clock time (seconds) #loops asynchrohous 8,192 0.0 1.1 3.6 12,800 synchrohous 8,192 0.0 3.4 180.3 12,800 위 결과에서 볼 수 있듯이 synchronous write 가 훨씬 더 느림 데이터베이스 시스템처럼 실제로 데이터가 디스크에 기록되었는지 여 부가 중요한 경우에 사용됨 50

12. Atomic operations 복수개의 스텝으로 구성된 operation으로 모든 스텝이 성공적으로 수행되거나, 전부 실패하거나 둘 중의 하나 부분적으로 성공하고 부분적으로 실패하는 경우는 없음 스텝이 실행되는 중간에 다른 operation 의 개입으로 영향을 받지 않 는다 51

Atomic operation 의 예 1 A) fd = open(, O_WRONLY O_APPEND); write(fd, buff, 100); B) fd = open(, O_WRONLY); lseek(fd, 0L, SEEK_END); write(fd, buff, 100); A)와 B)의 기능은 같다 step1) 먼저 current file offset 이 파일의 끝으로 이동한 후 step2) buff를 쓴다 52

A) 의 경우 step1) 과 step2) 는 write 시스템 호출 내부에서 실행 step1) 과 step2) 는 atomic operation B) 의 경우 step1) 은 lseek 시스템 호출 step2) 는 write 시스템 호출 step1) 과 step2) 는 atomic operation 이 아님 53

두 개 이상의 프로세스가 공유 파일에 대해서 write 하는 경우 10절의 파일 공유 3 에 해당 예) 여러 프로세스가 동일한 log 파일에 메시지를 추가하는 경우 A) 의 경우 Process 1 Process 2 write - step1 - step2 write - step1 - step2 54

B) 의 경우 Process 1 Process 2 lseek - step1 lseek step2 write step2 write step2 Process 1 과 Process 2 의 lseek step1 는 동일한 current file offset 을 설정함 Process 2 의 write step2 는 Process 1 의 write 를 덮어 쓰게 됨 55

Atomic operation 의 예 2 A) fd = open(pathname, O_WRONLY O_CREAT, mode); B) if ((fd = open(pathname, O_WRONLY)) < 0) { if (errno == ENOENT) fd = creat(pathname, mode); } A) 와 B) 의 기능은 동일 A) 는 atomic operation 56

고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 3장. 파일시스템 (Filesystem) 2004. 08. 22 1

Contents 1. stat(), fstat(), lstat() 2. File Type 3. File Access Permissions 4. access() 5. umask() 6. chmod(), fchmod() 7. Sticky bit 8. chown(), fchown(), lchown() 9. truncate(), ftruncate() 10. Filesystem 11. link() unlink() remove() rename() 12. Symbolic Links 13. File Times 14. Directory 15. sync(), fsync() 2

1. stat(), fstat(), lstat() #include <sys/types.h> #include <sys/stat.h> int stat (const char *pathname, struct stat *buf ); int fstat (int filedes, struct stat *buf ); int lstat (const char *pathname, struct stat *buf ); 주어진 파일에 대한 정보를 stat 구조체에 얻어 온다 리턴 값 : 성공하면 0, 실패하면 -1 buf : stat 구조체에 대한 포인터로 lstat()는 심볼릭 링크(symbolic link)가 가르키는 파일이 아니고 심볼릭 링크 자체에 대한 정보를 얻는다 3

stat 구조체 <sys/stat.h> 에 정의 struct stat { mode_t st_mode; /* file type & mode (permissions) */ ino_t st_ino; /* i-node number (serial number) */ dev_t st_dev; /* device number (filesystem) */ dev_t st_rdev; /* device number for special files */ nlink_t st_nlink; /* number of links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ off_t st_size; /* size in bytes, for regular files */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last file status change */ long st_blksize;/* best I/O block size */ long st_blocks; /* number of 512-byte blocks allocated */ }; 4

st_atime : 마지막으로 파일의 데이터를 읽은 시각 st_mtime : 마지막으로 파일의 데이터를 수정한 시각 st_ctime : 파일의 데이터가 아니고 이름이나 권한 같은 상태를 변경한 시각 st_blksize : 가장 효율적인 I/O 블럭 크기 (2장 8절 I/O 성능 참고, 8192 bytes) st_blocks : 파일이 차지하고 있는 공간의 크기를 512 byte 블럭의 수로 5

2. File Type 보통 파일 (Regular file) 데이터를 포함하고 있는 텍스트 또는 이진 화일 디렉토리 파일 (Directory file) 파일의 이름들과 파일 정보에 대한 포인터들을 포함 문자 특수 파일 (Character special file) 시스템에 장착된 어떤 장치를 가리키는 파일 문자 단위로 데이터를 전송하는 장치 블록 특수 파일 (Block special file) 시스템에 장착된 어떤 장치를 가리키는 파일 블럭 단위로 데이터를 전송하는 장치 6

FIFO 프로세스 간 통신에 사용되는 파일 named pipe 라고도 불림 소켓 (socket) 네트웍을 통한 프로세스 간 통신에 사용되는 파일 심볼릭 링크 (Symbolic link) 다른 파일을 가리키는 포인터 역할을 하는 파일 7

파일 타입 검사 파일 타입을 검사하는 매크로 함수 #include <sys/stat.h> S_ISREG() : 정규 파일 S_ISDIR() : 디렉토리 파일 S_ISCHR() : 문자 특수 파일 S_ISBLK() : 블록 특수 파일 S_ISFIFO() : pipe 또는 FIFO S_ISLNK() : 심볼릭 링크 S_ISSOCK() : 소켓 해당 종류의 파일이면 1, 아니면 0 을 리턴 stat 구조체의 st_mode 값을 검사함 8

파일 타입 상수 #include <sys/stat.h> S_IFREG : 정규 파일 S_IFDIR : 디렉토리 파일 S_IFCHR : 문자 특수 파일 S_IFBLK : 블록 특수 파일 S_IFFIFO : pipe 또는 FIFO S_IFLNK : 심볼릭 링크 S_IFSOCK : 소켓 S_ISxxx() 매크로 함수는 S_IFxxx 상수 값의 설정 여부를 판단 9

#include <sys/types.h> /* stat.c */ #include <sys/stat.h> int main(int argc, char *argv[]) { int i; struct stat buf; char *ptr; for (i = 1; i < argc; i++) { printf("%s: ", argv[i]); if (lstat(argv[i], &buf) < 0) { perror("lstat()"); continue; } } if (S_ISREG(buf.st_mode)) ptr = "regular"; else if (S_ISDIR(buf.st_mode)) ptr = "directory"; else if (S_ISCHR(buf.st_mode)) ptr = "character special"; else if (S_ISBLK(buf.st_mode)) ptr = "block special"; else if (S_ISFIFO(buf.st_mode)) ptr = "fifo"; else if (S_ISLNK(buf.st_mode)) ptr = "symbolic link"; else if (S_ISSOCK(buf.st_mode)) ptr = "socket"; else ptr = "** unknown mode **"; printf("%s\n", ptr); } exit(0); 10

[실행 결과] % a.out /etc /dev/ttya /bin a.out /etc: directory /dev/ttya: symbolic link /bin: symbolic link a.out: regular symbolic link 에 대한 정보도 얻기 위해서 stat() 대신 lstat() 를 사용 11

3. File Access Permissions file access permission bits (stat 구조체의 st_mode 의 값) #include <sys/stat.h> st_mode mask S_IRUSR S_IWUSR S_IXUSR S_IRGRP S_IWGRP S_IXGRP S_IROTH S_IWOTH S_IXOTH Meaning user-read user-write user-execute group-read group-write group-execute other-read other-write other-execute 12

UNIX 명령어 chmod file access permission 설정 stat 구조체의 st_mode UNIX 명령어 chown file 소유 user id 설정 stat 구조체의 st_uid UNIX 명령어 chgrp file 소유 group id 설정 stat 구조체의 st_gid 13

read 권한이 있어야 O_RDONLY O_RDWR 을 사용하여 파일을 열 수 있다 write 권한이 있어야 O_WRONLY O_RDWR O_TRUNC 을 사용하여 파일을 열 수 있다 디렉토리에 write 권한과 execute 권한이 있어야 그 디렉토리에 파일을 생성할 수 있고 그 디렉토리의 파일을 삭제할 수 있다 삭제할 때 그 파일에 대한 read write 권한은 없어도 됨 14

파일이 포함된 모든 상위 디렉토리에 대해 execute 권한이 있어야 그 파일을 열 수 있다 디렉토리에 대한 read 권한이 있어야 디렉토리 안에 들어 있는 파일 이름 목록을 읽을 수 있다 디렉토리에 대한 write 권한이 있어야 디렉토리에 파일을 생성 삭제 할 수 있다 디렉토리에 대한 execute 권한이 있어야 그 디렉토리나 그 하위 디렉 토리에 있는 파일을 열 수 있다 15

Effective User ID real user ID 와 real group ID 실제 사용자 ID 와 그 사용자가 속한 그룹 ID 로그인한 사용자 ID effective user ID 와 effective group ID 프로세스의 속성 file access permission 을 검사할 때 사용된다 대부분의 경우 real user ID 와 real group ID 가 사용되고 다음 슬라이드와 같은 경우만 예외 16

S_ISUID 와 S_ISGID stat 구조체의 st_mode 의 비트 S_ISUID : set-user-id S_ISGID : set-group-id st_mode 의 S_ISUID 비트가 설정된 실행 파일을 실행한 경우 그 실행 파일이 실행된 프로세스의 effective user ID 는 real user ID 가 아니고 st_uid : 그 실행 파일의 소유자 user ID st_mode 의 S_ISGID 비트가 설정된 실행 파일을 실행한 경우 그 실행 파일이 실행된 프로세스의 effective group ID 는 st_gid : 그 실행 파일의 소유자 group ID 17

S_ISUID, S_ISGID 가 설정된 실행 파일을 실행하는 경우는 real user ID, real group ID 의 권한이 아니고 그 파일 소유 user ID, group ID 의 권한으로 실행됨 예) $ ls -al /bin/passwd -r-sr-sr-x 1 root sys 23500 Jul 30 2003 /bin/passwd* 18

4. access() #include <unistd.h> int access (const char *pathname, int mode ); real user ID와 real group ID로 파일의 permission 체크 리턴 값: 성공하면 0, 실패하면 -1 mode 값 mode R_OK W_OK X_OK F_OK Description test for read permission test for write permission test for execute permission test for existence of tile 19

#include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include "error.h" int main(int argc, char *argv[]) { if (argc!= 2) halt("usage: a.out <pathname>"); if (access(argv[1], R_OK) < 0) error("r_ok"); else printf("read access OK\n"); if (open(argv[1], O_RDONLY) < 0) error("o_rdonly"); else printf("open for reading OK\n"); } return 0; 20

5. umask() #include <sys/types.h> #include <sys/stat.h> mode_t umask (mode_t cmask ); 파일 생성 시 적용할 마스크 값 설정 리턴 값: 기존의 마스크 값 cmask: bitwise OR S_IRUSR, S_IWUSR, S_IXUSR S_IRGRP, S_IWGRP, S_IXGRP S_IROTH, S_IWOTH, S_IXOTH umask() 호출 후 파일을 생성할 때는 cmask 에 설정된 bit 들이 꺼진 다 UNIX 명령어 : umask 참조 21

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "error.h" int main(void) { umask(0); if (creat("foo", S_IRUSR S_IWUSR S_IRGRP S_IWGRP S_IROTH S_IWOTH) < 0) error("foo"); } umask(s_irgrp S_IWGRP S_IROTH S_IWOTH); if (creat("bar", S_IRUSR S_IWUSR S_IRGRP S_IWGRP S_IROTH S_IWOTH) < 0) error("bar"); return 0; 22

[실행 결과] % a.out % ls -al foo bar -rw------- 1 lsj 없음 0 Jul 21 11:54 bar -rw-rw-rw- 1 lsj 없음 0 Jul 21 11:54 foo % umask 22 23

6. chmod(), fchmod() #include <sys/stat.h> #include <sys/types.h> int chmod (const char *pathname, mode_t mode ); int fchmod (int filedes, mode_t mode ); 파일에 대해 access permission 을 변경한다 stat 구조체의 st_mode 변경 리턴 값: 성공하면 0, 실패하면 -1 mode : bitwise OR S_ISUID, S_ISGID, S_ISVTX S_IRUSR, S_IWUSR, S_IXUSR S_IRGRP, S_IWGRP, S_IXGRP S_IROTH, S_IWOTH, S_IXOTH 24

#include <sys/types.h> #include <sys/stat.h> #include "error.h" int main() { struct stat statbuf; /* turn on set-group-id and turn off group-execute */ if (stat("foo", &statbuf) < 0) error("stat(foo)"); if (chmod("foo", (statbuf.st_mode & ~S_IXGRP) S_ISGID) < 0) error("chmod(foo)"); /* set absolute mode to "rw-r--r--" */ if (chmod("bar", S_IRUSR S_IWUSR S_IRGRP S_IROTH) < 0) error("chmod(bar)"); } return 0; 25

[실행 결과] $ ls -l foo bar -rw------- 1 lsj 없음 0 Jul 21 12:04 bar -rw-rw-rw- 1 lsj 없음 0 Jul 21 12:04 foo $ a.out $ ls -l foo bar -rw-r--r-- 1 lsj 없음 0 Jul 21 12:04 bar -rw-rwlrw- 1 lsj 없음 0 Jul 21 12:04 foo 26

foo 파일의 set-group-id bit 를 켜고, group-execute bit 를 끄다 à mandatory record locking 활성화 à ls 의 출력에서 group-execute permisson 문자가 'l' ls 출력에서 foo 와 bar 의 날짜가 변경되지 않는다 chmod 는 stat 구조체의 st_ctime 만을 변경 ls 는 stat 구조체의 st_mtime 을 출력 27

chmod() 의 mode 상수 값 #include <sys/stat.h> mode S_ISUID S_ISGID S_ISVTX S_IRWXU S_IRUSR S_IWUSR S_IXUSR S_IRWXG S_IRGRP S_IWGRP S_IXGRP S_IRWXO S_IROTH S_IWOTH S_IXOTH Description set-user-id on execution set-group-id on execution saved-text (sticky bit) read, write, and execute by user (owner) read by user (owner) write by user (owner) execute by user (owner) read, write, and execute by group read by group write by group execute by group read, write, and execute by other (world) read by other (world) write by other (world) execute by other (world) 28

7. Sticky bit (S_ISVTX) S_ISVTX 비트의 기원 sticky bit 가 설정된 실행 파일은 프로그램의 종료 후 swap 영영 에 저장하여 프로그램의 재실행 시 빠르게 메모리에 로드할 수 있도록 함 자주 사용되는 실행 파일의 경우에 설정 초기의 느린 디스크 입출력 속도 때문에 사용되었으나 현재는 가상 메모리 기법과 빠른 파일 시스템으로 인하여 이런용도로 사용되지 않는다 29

현재 시스템에서 Sticky bit 는 특수한 디렉토리를 설정하는데 사용 파일을 지우거나 이름을 바꾸려고 할 때 보통의 디렉토리는 사용자가 디렉토리에 대한 쓰기 권한만 있으면 가능 Sticky bit 가 설정된 디렉토리는 파일의 소유자이거나, 디렉토리의 소유자이거나, 슈퍼 유저인 경 우에만 그 디렉토리의 파일을 지우거나 이름을 바꿀 수 있다. Sticky bit 는 슈퍼 유저만 설정할 수 있다 30

Sticky bit 디렉토리의 예: /tmp 임시 파일 디렉토리 모든 사용자에게 쓰기 권한이 있어서 파일을 만들 수 있다 그러나 자신의 소유 파일만 삭제하거나 이름을 바꿀 수 있다 $ ls ld /tmp drwxrwxrwt 7 root sys 5628 Jul 21 12:50 /tmp/ à ls 의 출력에서 other-execute permisson 문자가 't' 31

8. chown(), fchown(), lchown() #include <sys/types.h> #include <unistd.h> int chown (const char *pathname, uid_t owner, gid_t group ); int fchown (int filedes, uid_t owner, gid_t group ); int lchown (const char *pathname, uid_t owner, gid_t group ); 파일의 user ID와 group ID를 변경한다. stat 구조체의 st_uid, st_gid 변경 리턴 : 성공하면 0, 실패하면 -1 lchown()은 심볼릭 링크(symbolic link)가 가르키는 파일이 아니고 심볼릭 링크 자체를 변경한다 Berkeley 기반 시스템에서는 super-user만 변환 가능 System V 계열 시스템은 일반 사용자도 변경 가능 (_POSIX_CHOWN_RESTRICTED 값에 의해 결정) 32

9. truncate(), ftruncate() #include <sys/types.h> #include <unistd.h> int truncate (const char *pathname, off_t length ); int ftruncate (int filedes, off_t length ); 파일의 크기를 length 로 줄인다 리턴 : 성공하면 0, 실패하면 -1 33

10. Filesystem disk drive partition partition partition i-list directory blocks and data blocks boot block(s) super block i-node i-node... i-node 34

i-node 하드 디스크에 저장되어 있는 자료구조 파일에 대한 정보를 가지고 있음 file type access permission bits file size pointers to data blocks for the file stat 구조체의 필드는 i-node 에서 읽어온다 35

directory blocks and data blocks i-list data block data block directory block data block directory block i-list i-node i-node... i-node directory block i-node number filename directory block i-node number filename 36

directory block 은 파일 목록을 저장 파일 이름과 그 파일의 i-node number hard link directory block 의 파일 이름과 i-node 와의 연결 i-node number 로 연결 UNIX 명령어 ln 참고 i-node number filesystem 의 i-list 에서 i-node 의 일련번호 따라서 hard link 는 같은 filesystem 내부에서만 가능 37

symbolic link 파일의 내용(data block의 내용)은 링크 대상 파일의 pathname 예) lrwxrwxrwx 1 root 7 Sep 25 07:14 lib -> usr/lib 파일 이름은 lib 파일 내용은 usr/lib 파일 크기 7 bytes UNIX 명령어 ln s 참고 i-node 의 link count stat 구조체의 st_nlink 이 i-node 를 가르키는 directory entry 수 앞 슬라이드 그림에서 두 directory entry 는 동일한 i-node 를 가르키므로 link count 는 2 38

파일의 삭제 directory block 에서 파일을 삭제하면 i-node 의 link count 가 하나 감소 link count 가 0 에 도달하면 그 파일의 i-node 와 data block 이 삭제됨 파일의 이동 UNIX 명령어 mv 파일의 data block 이나 i-node 의 변화는 없이 directory entry 만 변경됨 39

directory blocks and data blocks i-list data block data block directory block directory block i-node 0 i-node 1267 i-node 2549 directory block 2549. 1267.. directory block 1267 i-node... 2549 testdir 40

testdir 디렉토리의 i-node number는 2549 testdir의 부모 디렉토리 i-node number는 1267 i-node 2549의 link count는 최소 2 i-node 1267의 link count는 최소 3 41

11. link() #include <unistd.h> int link (const char *existingpath, const char *newpath ); 이미 존재하는 파일(existingpath)에 대해서 새로운 디렉토리 항목 (newpath)을 만든다 리턴 값: 성공하면 0, 실패하면 -1 42

hard link 가 만들어짐 같은 i-node를 가리키는 directory entry 가 하나 더 만들어짐 그 i-node의 link count 가 하나 증가 hard link는 하나의 파일시스템 내부에서만 가능 43

unlink() #include <unistd.h> int unlink (const char *pathname); 파일의 link count를 감소 시킴 리턴 값: 성공하면 0, 실패하면 -1 unlink()는 directry entry를 지우며, 파일의 link count를 1 감소 시킨다 link count 가 0이 되면, 파일을 디스크에서 제거한다. i-node와 data block 삭제 44

다른 프로세스가 사용중인 파일이 삭제되는 것을 방지하기 위해 link count가 0에 도달했더라도 그 파일을 open 한 프로세스의 수가 0 이상이면 삭제하지 않는다 파일이 close 될 때 kernel은 그 파일을 open 한 프로세스 수가 0 인 지 확인하고, 0 일 경우 link count가 0 인지 확인하고 삭제한다 45

#include <sys/types.h> /* unlink.c */ #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include "error.h" int main() { int fd, len; char buf[20]; fd = open("tempfile", O_RDWR O_CREAT O_TRUNC, 0666); if (fd == -1) error("open1"); unlink("tempfile"); len = write(fd, "How are you?", 12); if (len!= 12) error("write"); lseek(fd, 0L, SEEK_SET); len = read(fd, buf, sizeof(buf)); if (len < 0) error("read"); buf[len] = '\0'; printf("%s\n", buf); close(fd); } fd = open("tempfile", O_RDWR); if (fd == -1) error("open2"); close(fd); return 0; 46

remove() #include <unistd.h> int remove (const char *pathname); 파일의 link count를 감소 시킴 리턴 값: 성공하면 0, 실패하면 -1 pathname이 파일이면 unlink()와 같은 일을 하고, 디렉토리이면 rmdir()과 같은 일을 한다 47

rename() #include <unistd.h> int rename (const char *oldname, const char *newname ); 파일이나 디렉토리의 이름을 바꾼다. 리턴 값: 성공하면 0, 실패하면 -1 newname이 이미 존재하는 경우 oldname이 파일을 가리키고 newname이 파일로서 존재할 때, 기존 을 파일을 덮어 쓴다. oldname이 디렉토리를 가리키고 newname이 비어 있는 디렉토리일 때, 기존의 디렉토리를 덮어 쓴다. 48

12. Symbolic Links 심볼릭 링크(symbolic link)는 파일에 대한 간접적인 포인터 실제 파일에 대한 경로를 저장하고 있다 링크의 한계점을 극복 링크는 단일 파일시스템에서만 허용된다 디렉토리에 대한 링크는 수퍼 유저만 만들 수 있다 49

파일을 다루는 함수를 사용할 때 심볼릭 링크를 자체를 다루는지 아 니면 링크된 대상 파일을 다루는지 심볼릭 링크 자체를 다루는 함수 lchown, lstat, readlink, remove, rename, unlink 등 링크된 대상 파일을 다루는 함수 access, chdir, chmod, chown, creat, exec, link, mkdir, mkfifo, open, opendir, pathconf, stat, truncate 등 50

symlink() #include <unistd.h> int symlink (const char *actualpath, const char *sympath ); 심볼릭 링크를 만든다 심볼릭 링크 파일의 내용은 actualpath 심볼릭 링크 파일의 크기는 actualpath 문자열의 길이 리턴 값: 성공하면 0, 실패하면 -1 actualpath : 실제 파일 sympath : 만들 심볼릭 링크의 이름 51

readlink() #include <unistd.h> int readlink (const char *pathname, char *buf, int bufsize ); 심볼릭 링크 파일의 내용을 읽는 함수 symlink() 에서 저장된 actualpath 가 buf에 채워진다 null 문자는 채워지지 않는다 리턴 값: 성공하면 읽은 문자열의 길이, 실패하면 -1 심볼릭 링크를 open 으로 열면 링크된 대상 파일이 열린다 52

13. File Times stat 구조체의 st_atime 파일의 데이터가 마지막으로 읽혔던 시간 read() 호출 stat 구조체의 st_mtime 파일의 데이터가 마지막으로 변경된 시간 write () 호출 stat 구조체의 st_ctime 파일의 stat 구조의 내용이 마지막으로 변경된 시간 chmod(), chown() 호출 UNIX 명령어 ls 의 l u c 옵션 참고 53

utime() #include <sys/types.h> #include <utime.h> int utime (const char *pathname, const struct utimbuf *times ); 파일의 최종 접근 시간과 최종 변경 시간을 조정한다. times가 NULL 이면, 현재시간으로 설정된다. 리턴 값: 성공하면 0, 실패하면 -1 UNIX 명령어 touch 참고 54

struct utimbuf { time_t actime; /* access time */ time_t modtime; /* modification time */ } 각 필드는 1970-1-1 00:00 부터 현재까지의 경과 시간을 초로 환산한 값 55

#include <sys/types.h> /* utime.c */ #include <sys/stat.h> #include <fcntl.h> #include <utime.h> #include "error.h" int main(int argc, char *argv[]) { int i; struct stat statbuf; struct utimbuf timebuf; } for (i = 1; i < argc; i++) { if (stat(argv[i], &statbuf) < 0) /* fetch current times */ error(argv[i]); if (open(argv[i], O_RDWR O_TRUNC) < 0) /* truncate */ error(argv[i]); timebuf.actime = statbuf.st_atime; timebuf.modtime = statbuf.st_mtime; if (utime(argv[i], &timebuf) < 0) /* reset times */ error(argv[i]); } return 0; 56

앞 슬라이드의 예제 (utime.c) 1) 파일의 내용을 truncate 하기 전에 파일의 utime과 atime을 읽음 2) 파일의 내용을 truncate 하면 utime과 atime이 현재 시각으로 변 경됨 3) 저장해둔 utime과 atime으로 복구 4) 파일의 크기는 0으로 변화했지만 utime과 atime은 변화 없음 [실행 결과] % ls -lu afile -rw-r--r-- 1 lsj user 14 Jul 1 09:10 afile % a.out afile % ls -lu afile -rw-r--r-- 1 lsj user 0 Jul 1 09:10 afile 57

14. Directory 디렉토리 파일 일종의 파일이므로 open, read, close 함수 등을 사용할 수 있다 디렉토리 파일 사용에 편리한 새로운 함수들도 제공된다. 디렉토리 파일의 내용은 구조체 dirent의 배열 file name : 파일 이름, 하위 디렉토리 이름, ".", ".." i-node number #include <dirent.h> struct dirent { ino_t d_ino; /* i-node number */ char d_name[name_max + 1]; /* filename */ } 58

DIR 구조체 오픈된 디렉토리를 다루는데 사용되는 구조체 표준 I/O 라이브러리의 FILE 구조체와 비슷한 역할 59

opendir(), readdir(): 디렉토리 접근 #include <sys/types.h> #include <dirent.h> DIR *opendir (const char *pathname); struct dirent *readdir(dir *dp); opendir()로 디렉토리 파일을 열고 readdir()로 디렉토리 파일의 내용을 읽는다 리턴 값: 성공하면 구조체 주소, 실패하면 NULL readdir()로 읽을 때마다 디렉토리 파일의 current file offset은 읽 은 구조체 dirent의 크기 만큼 증가한다. 60

디렉토리의 항목 읽기 위해서는 해당 디렉토리에 대한 읽기 권한이 있어야 한다 그러나 쓰기권한이 있어도 write 함수로 직접 쓸 수는 없다. mkdir rmdir 를 사용해야함 사용자는 디렉토리에 대해서 쓰기 작업을 직접 수행할 수는 없다. 61

rewinddir(), closedir() #include <sys/types.h> #include <dirent.h> void rewinddir (DIR *dp); int closedir (DIR *dp); rewinddir() 디렉토리 파일의 current file offset을 처음으로 옮긴다 closedir() 디렉토리 파일을 닫는다. 리턴 값: 성공하면 0, 실패하며 -1 62

mkdir() #include <sys/types.h> #include <sys/stat.h> int mkdir (const char *pathname, mode_t mode ); 새로운 디렉토리를 만든다. 리턴 값: 성공하면 0, 실패하면 -1 성공하면 "." 와 ".." 파일은 자동적으로 만들어진다. "."은 이 디렉토리 파일의 i-node를, ".."은 부모 디렉토리 파일의 i-node를 가르킨다 63

rmdir() #include <unistd.h> int rmdir (const char *pathname ); 비어 있는 디렉토리를 삭제한다. 디렉토리 파일의 link count를 감소 시킴 link count가 0이 되면 삭제됨 리턴 값: 성공하면 0, 실패하면 -1 64

#include <sys/types.h> /* listfiles.c */ #include <sys/stat.h> #include <dirent.h> #include <stdio.h> #include "error.h" /* typeoffile - return the letter indicating the file type. */ char typeoffile(mode_t mode) { switch (mode & S_IFMT) { case S_IFREG: return('-'); case S_IFDIR: return('d'); case S_IFCHR: return('c'); case S_IFBLK: return('b'); case S_IFLNK: return('l'); case S_IFIFO: return('p'); case S_IFSOCK: return('s'); } return('?'); } 65

/* permoffile - return the file permissions in an "ls"-like string. */ char* permoffile(mode_t mode) { int i; char *p; static char perms[10]; } p = perms; strcpy(perms, "---------"); /* The permission bits are three sets of three * bits: user read/write/exec, group read/write/exec, * other read/write/exec. We deal with each set * of three bits in one pass through the loop. */ for (i=0; i < 3; i++) { if (mode & (S_IREAD >> i*3)) *p = 'r'; p++; if (mode & (S_IWRITE >> i*3)) *p = 'w'; p++; if (mode & (S_IEXEC >> i*3)) *p = 'x'; p++; } /* Put special codes in for set-user-id, set-group-id, * and the sticky bit. (This part is incomplete; "ls" * uses some other letters as well for cases such as * set-user-id bit without execute bit, and so forth.) */ if ((mode & S_ISUID)!= 0) perms[2] = 's'; if ((mode & S_ISGID)!= 0) perms[5] = 's'; if ((mode & S_ISVTX)!= 0) perms[8] = 't'; return(perms); 66

/* outputstatinfo - print out the contents of the stat structure. */ void outputstatinfo(char *pathname, char *filename, struct stat *st) { int n; char slink[bufsiz+1]; } /* Print the number of file system blocks, permission bits, * number of links, user-id, and group-id. */ printf("%5d ", st->st_blocks); printf("%c%s ", typeoffile(st->st_mode), permoffile(st->st_mode)); printf("%3d ", st->st_nlink); printf("%5d/%-5d ", st->st_uid, st->st_gid); /* If the file is not a device, print its size; otherwise * print its major and minor device numbers. */ if (((st->st_mode & S_IFMT)!= S_IFCHR) && ((st->st_mode & S_IFMT)!= S_IFBLK)) printf("%9d ", st->st_size); else printf("%4d,%4d ", major(st->st_rdev), minor(st->st_rdev)); /* Print the access time. The ctime() function is * described in Chapter 7, "Time of Day Operations." */ printf("%.12s ", ctime(&st->st_mtime) + 4); /* Print the file name. If it's a symblic link, also print * what it points to. */ printf("%s", filename); if ((st->st_mode & S_IFMT) == S_IFLNK) { if ((n = readlink(pathname, slink, sizeof(slink))) < 0) printf(" ->???"); else printf(" -> %.*s", n, slink); } 67

int main(int argc, char **argv) { DIR *dp; char *dirname; struct stat st; struct dirent *d; char filename[bufsiz+1]; /* For each directory on the command line... */ while (--argc) { dirname = *++argv; /* Open the directory */ if ((dp = opendir(dirname)) == NULL) error(dirname); printf("%s:\n", dirname); /* For each file in the directory... */ while ((d = readdir(dp))!= NULL) { /* Create the full file name. */ sprintf(filename, "%s/%s", dirname, d->d_name); /* Find out about it. */ if (lstat(filename, &st) < 0) error(filename); /* Print out the information. */ outputstatinfo(filename, d->d_name, &st); putchar('\n'); } putchar('\n'); closedir(dp); } return 0; } 68

chdir(), fchdir() #include <unistd.h> int chdir (const char *pathname); int fchdir (int filedes); 현재 작업 디렉토리를 변경한다 반환 값: 성공하면 0, 실패하면 -1 현재 작업 디렉토리는 프로세스의 속성 69

getcwd() #include <unistd.h> char *getcwd (char *buf, size_t size ); 현재 작업 디렉토리 경로명을 얻는다 리턴 값: 성공하면 buf의 주소, 실패하면 NULL 70

#include <unistd.h> #include <stdio.h> #include "error.h" #define PATH_MAX 1024 int main(void) { char path[path_max+1]; if(chdir("/tmp")<0) error("error chdir"); else { if(getcwd(path, PATH_MAX) == NULL) error("error getcwd"); else printf("current working directory changed to %s \n", path); } } 71

15. sync(), fsync() #include <unistd.h> void sync (); int fsync(int filedes); 버퍼에 있는 내용을 디스크에 쓰도록 한다. sync()는 시스템 데몬 프로세스에 의해서 30초마다 호출된다. I/O 작업이 끝나기 전에 리턴한다 fsync()는 지정된 파일에 대해서만 I/O 작업을 수행하도록 한다. I/O 작업이 끝난 후 리턴한다 참고) O_SYNC 플래그 72

고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 4장. 표준 입출력 라이브러리 (Standard I/O Library) 2004. 08. 22 1

Contents 1. Standard I/O Library 2. Buffing 3. Opening a Stream: fopen() 4. Reading / Writing a Stream 5. Standard I/O Efficiency 6. Binary I/O: fread() 7. Positioning a Stream 8. Formatted I/O 9. Temporary Files 2

1. Standard I/O Library Written by Dennis Ritchie in 1975 Implemented on many OS ANSI C Standard Library Buffer allocation 최적의 크기 단위로 I/O를 수행 디스크 I/O 횟수 최소화 Streams 문자의 흐름으로 파일 입출력을 다룬다 3

System calls vs. C Library functions application code user process C library functions C library buffers system calls system buffers (buffer caches) kernel hardware (harddisk ) 4

FILE 구조체 3장의 파일 관련 시스템 호출 함수 à 파일 디스크립터 (file descriptor) 표준 입출력 함수 à FILE 구조체에 대한 포인터 하나의 스트림을 다루기 위한 정보를 포함하는 구조체 파일 디스크립터 (File descriptor) 버퍼에 대한 포인터, 버퍼 크기 에러 플래그 등 #include <stdio.h> 5

FILE 구조체 FILE * (FILE 구조체에 대한 포인터) 스트림을 열면 (fopen 함수) 리턴됨 표준 I/O 함수들의 파라미터로 전달해야함 프로그래머는 FILE 구조체의 내부를 알 필요 없음 6

FILE 구조체 typedef struct { int _cnt; unsigned char *_ptr; unsigned char *_base; unsigned char _flag; unsigned char _file; } FILE ; _cnt : 버퍼에 남아 있는 문자의 수 _ptr : 버퍼 내에 다음에 쓸(읽을) 위치를 가리키는 포인터 _base : 버퍼 시작 주소 _flag : 스트림의 현재 상태 _IOFBF, _IOLBF, _IONBUF _IOEOF, _IOERR _IOREAD, _IOWRT _file : 파일 디스크립터 7

표준 입력/출력/에러 스트림 (stream) stdin, stdout, stderr FILE* #include <stdio.h> 파일 디스크립터 (file descriptorint) STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO int #include <unistd.h> 8

2. Buffing C library buffer 사용 목적 디스크 I/O 수행의 최소화 read (), write () 함수 호출의 최소화 최적의 크기 단위로 I/O 수행 시스템 성능 향상 C library buffer 방식 fully buffered line buffered unbuffered 9

C library buffer 방식 Fully Buffered 버퍼가 꽉 찼을 때 실제 I/O 수행 디스크 파일 입출력 Line Buffered 줄 바꿈 문자(newline)에서 실제 I/O 수행 터미널 입출력 (stdin, stdout) Unbuffered 버퍼를 사용하지 않는다. 표준 에러 (stderr) 10

setbuf() setvbuf() #include <stdio.h> void setbuf (FILE *fp, char *buf ); int setvbuf (FILE *fp, char *buf, int mode, size_t size ); 버퍼의 관리 방법을 변경한다 호출 시기 스트림이 오픈된 후, 입출력 연산 수행 전에 호출되어야 함 11

setbuf() void setbuf (FILE *fp, char *buf ); 버퍼 사용을 on/off 할 수 있다. buf 가 NULL 이면 unbuffered buf 가 BUFSIZ 크기의 공간을 가리키면 fully/line buffered 터미날 장치면 line buffered 그렇지 않으면 fully buffered 12

setvbuf() int setvbuf (FILE *fp, char *buf, int mode, size_t size ); 버퍼 사용 방법을 변경 리턴 값: 성공하면 0, 실패하면 nonzero mode _IOFBF : fully buffered _IOLBF : line buffered _IONBF : unbuffered 13

setvbuf() mode == _IONBF buf 와 size 는 무시됨 mode == _IOLBF or _IOFBF buf 가 NULL이 아니면 buf 에서 size 만큼의 공간 사용 NULL이면 라이브러리가 알아서 적당한 크기 할당 사용 stat 구조체의 st_blksize 크기 할당 (disk files) st_blksize 값을 알 수 없으면 BUFSIZ 크기 할당 (pipes) 14

setvbuf() Function mode buf Buffer & length Type of buffering setbuf nonnull user buf of length BUFSIZ fully or line buffered NULL no buffer unbuffered setvbuf _IOFBF nonnull user buf of length size fully buffered NULL System buffer of appropriate length _IOLBF nonnull user buf of length size line buffered NULL System buffer of appropriate length _IONBF ignored no buffer unbuffered 일반적으로 표준 C 라이브러리가 버퍼의 크기를 결정하고 할당하도록 하는 것이 좋다 15

#include <stdio.h> /* buffer.c */ main() { char buf[bufsiz]; } printf("hello, "); sleep(1); printf("unix!"); sleep(1); printf("\n"); sleep(1); setbuf(stdout,null); printf("how "); sleep(1); printf("are "); sleep(1); printf("you?"); sleep(1); printf("\n"); sleep(1); 16

fflush() #include <stdio.h> int fflush (FILE *fp); fp 스트림의 출력 버퍼에 남아있는 내용을 write() 시스템 호출을 통 하여 커널에 전달한다 리턴 값 : 성공하면 0, 실패하면 EOF (-1) fp 가 NULL이면, 모든 출력 스트림의 출력 버퍼에 남아있는 내용을 커널에 전달한다 17

3. Opening a Stream: fopen() #include <stdio.h> FILE *fopen (const char *pathname, const char *type); 파일을 스트림으로 연다 리턴 값: 성공하면 FILE *, 실패하면 NULL fopen () 함수는, FILE 구조체의 각 필드들을 초기화 한 후에 open() 함수를 호출한다. 18

fopen() - type type 파라미터 "r", "rb" "w", "wb" "a", "ab" "r+", "r+b", "rb+" "w+", "w+b", "wb+" "a+", "a+b", "ab+" Description open for reading O_RDONLY truncate to 0 length or create for writing O_WRONLY O_CREAT O_TRUNC append; open for writing at end of file, or create for writing O_WRONLY O_APPEND O_CREAT open for reading and writing O_RDWR truncate to 0 length or create for reading and writing O_RDWR O_CREAT O_TRUNC open or create for reading and writing at end of file O_RDWR O_APPEND O_CREAT 19

fopen() - type Restriction r w a r+ w+ a+ file must already exist o o previous contents of file discarded o o stream can be read o o o o stream can be wirtten o o o o o stream can be wirtten only an end o o 20

fopen() - "b" "b" 를 지정해주면 binary option, 지정해 주지 않으면 text option FTP 의 binary 명령과 같은 효과 UNIX에서는 à 아무 효과 없음 Windows 운영체제에서 binary option à 아무 효과 없음 Windows 운영체제에서 text option 일 경우 '\n' 을 출력하면 '\r', '\n' 으로 자동 변환됨 '\r', '\n' 을 읽으면 '\n' 으로 자동 변환됨 21

제한사항 출력 함수 다음에 입력함수를 호출하기 위해서는, 사이에 fflush(), fseek(), fsetpos(), rewind() 등의 함수를 반드시 호출해야 한다. 입력 함수 다음에 출력함수를 호출하기 위해서는, 사이에 fseek(), fsetpos(), rewind() 등의 함수를 호출하거나 입력 연산이 파일의 끝 에 도달했어야 한다. 파일이 새로 생성될 경우에, 새로 생성하는 파일에 대한 permission S_IRUSR S_IWUSR S_IRGRP S_IWGRP S_IROTH S_IWOTH POSIX.1 표준 22

freopen() #include <stdio.h> FILE *freopen (const char *pathname, const char *type, FILE *fp ); fp 가 가리키는 스트림으로 파일을 연다 fp 가 이미 열려진 스트림이면 새로 열기 전에 먼저 닫는다 stdin, stdout, stderr 스트림으로 파일을 열 때 사용한다 리턴 값 : 성공하면 FILE* fp, 실패하면 NULL type : fopen()에서와 같음 23

#include <fcntl.h> /* freopen.c */ #include <stdio.h> #include "error.h" main() { FILE* f; } printf("this is displayed on the screen.\n"); if((f = freopen("afile", "w", stdout)) == NULL) error("freopen"); printf("this is written into the redirected file.\n"); 24

fdopen() #include <stdio.h> FILE *fdopen (int filedes, const char *type); 이미 열려진 파일 디스트립터 (filedes)에 대해, 표준 입출력의 스트 림을 생성하여 리턴한다 파일 디스트립터 -> FILE * pipe, cummunication channel 등을 열 때 사용 25

fclose() #include <stdio.h> int fclose ( FILE *fp ); 스트림을 닫는다 리턴 값: 성공하면 0, 실패하면 EOF (-1) 출력 버퍼에 있는 모든 자료는 파일에 저장되고, 입력 버퍼에 있는 모든 자료는 버려진다. 프로세스가 정상적으로 종료한 경우에는 모든 열려진 스트림이 저절 로 닫힌다 26

4. Reading / Writing a Stream 3 types of Unformatted I/O: Character-at-a-time I/O: getc(), fgetc(), getchar() Line-at-a-time I/O: fgets(), fputs() Direct I/O: fread(), fwrite() read/write some number of objects Formatted I/O: scanf(), fscanf(), printf(), fprintf() 27

getc() fgetc() getchar() #include <stdio.h> int getc (FILE *fp ); int fgetc (FILE *fp ); int getchar (void ); 스트림에서 한 문자를 읽어온다 Return: next char if OK, EOF on EOF or error 28

getc() fgetc() getchar() getc()는 매크로 함수 인자로 side effect 없는 수식을 사용하여야 한다 함수의 주소를 얻을 수 없다 fgetc()는 함수 함수의 주소를 사용할 수 있다 수행 시간은 getc()가 빠르다 getchar()는 getc(stdin)과 같다 29

에러검사: ferror() feof() #include <stdio.h> int ferror (FILE *fp); int feof (FILE *fp); void clearerr (FILE *fp); 스트림 입력 함수가 EOF 를 리턴했을 때, feor() : 파일의 끝에 도달했는지 확인 ferror() : 에러가 발생했는지 확인 clearerr()는 EOF 상태나 에러 상태를 지운다 30

ungetc() #include <stdio.h> int ungetc (int c, FILE *fp ); 문자를 스트림에 다시 되돌림 리턴 값: 성공하면 c, 실패하면 EOF c 는 원래 읽었던 문자일 필요는 없음 단어나 토큰(token) 단위로 읽을 때 사용 다음 문자가 무엇인지 미리 읽고 난 후 되돌릴 때 31

putc() fputc() putchar() #include <stdio.h> int putc (int c, FILE *fp ); int fputc (int c, FILE *fp ); int putchar (int c ); 스트림에 한 문자를 쓴다 Return: c if OK, EOF on error 32

putc() fputc() putchar() putc()는 매크로 함수 인자로 side effect 없는 수식을 사용하여야 한다 함수의 주소를 얻을 수 없다 fputc()는 함수 함수의 주소를 사용할 수 있다 수행 시간은 putc()가 빠르다 putchar()는 putc(stdout)과 같다 33

fgets() #include <stdio.h> char *fgets (char *buf, int n, FILE *fp ); '\n' 문자까지 한줄을 입력받는다 '\n' 문자도 읽혀지고 '\0' 이 채워진다 n - 1 개 이상의 문자열을 읽을 수는 없다 Return buf if OK, NULL on end of file or error 34

gets() #include <stdio.h> char *gets (char *buf ); 표준 입력으로부터 한 줄을 읽어 들인다 '\n' 문자를 buf 에 저장하지 않는다. deprecated function buffer overflow 에러가 발생할 수 있으므로 바람직하지 않다 Return buf if OK, NULL on end of file or error 35

fputs() puts() #include <stdio.h> int fputs (const char *str, FILE *fp ); int puts (const char *str); 문자열을 스트림에 출력한다 puts() 는 stdout에 출력하고, '\n'을 덧붙인다 Return nonnegative value if OK, EOF on error 36

5. Standard I/O Efficiency How does the three types of unformatted I/O compare in efficiency? How does unformatted I/O compare with direct read() and write()? Are macros more efficient than functions? Why? What about Program Text size? 37

#include <stdio.h> /* fputc.c */ #include "error.h" #define FILESIZE (100 * 1024 * 1024) main() { FILE* f; int i, fd; if ((f = fopen("file.write", "w")) == NULL) error("file.write"); for (i=0; i < FILESIZE; ++i) fputc('.', f); } fclose(f); 38

Function User CPU (seconds) System CPU (seconds) Clock time (seconds) #loops write() (write2.c) 140.9 1,378.1 1,527.8 104,857,600 User CPU (seconds) System CPU (seconds) Clock time (seconds) #loops Bytes of program text fputc() (fputc.c) putc() (putc.c) 16.1 1.4 21.1 104,857,600 980 7.8 1.1 11.1 104,857,600 1056 39

6. Binary I/O: fread() #include <stdio.h> size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp ); 스트림에서 이진 데이터를 읽는다 size 크기의 객체를 nobj 개 ptr 에 읽어들인다 리턴 값: 읽은 객체의 수 리턴 값이 nobj 값보다 작으면 파일의 끝이거나 에러 ferror(), feof() 40

fwrite() #include <stdio.h> size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp ); 스트림에 이진 데이터를 출력한다 size 크기의 객체를 nobj 개 출력한다 리턴 값: 출력된 객체의 수 41

Binary Data Exchange May be incompatible among different machine architectures because: Offset of a member in a structure can differ between compilers and systems Binary formats of int and float may differ between different machines (little endian, big endian) So use a higher level protocol instead! 42

7. Positioning a Stream #include <stdio.h> long ftell (FILE *fp ); int fseek (FILE *fp, long offset, int whence ); void rewind (FILE *fp); ftell() - 파일의 현재 위치를 리턴, -1 on error fseek() 파일의 현재 위치를 변경 (lseek() 참고) whence : SEEK_SET, SEEK_CUR, SEEK_END Returns: 0 if OK, nonzeron on error rewind() 파일의 현재 위치를 파일 선두로 변경 fseek (fp, 0L, SEEK_SET) 43

fgetpos() fsetpos() #include <stdio.h> int fgetpos (FILE *fp, fpos_t *pos ); int fsetpos (FILE *fp, const fpos_t *pos ); 새 ANSI C 표준, fpos_t 형 도입 fgetpos() 파일의 현재 위치를 pos 에 얻는다 fsetpos() 파일의 현재 위치를 pos 로 설정 Return 0 if OK, nonzero on error 44

8. Formatted I/O Formatted Output printf() fprintf() sprintf() vprintf() vfprintf() vsprintf() Formatted Input scanf() fscanf() sscanf() 45

printf() fprintf() sprintf() #include <stdio.h> int printf (const char *format, ); int fprintf (FILE *fp, const char *format, ); int sprintf (char *buf, const char *format, ); printf() - stdout 에 출력 fprintf() - fp 스트림에 출력 Both return: number of characters output if OK, negative value if output error sprintf() 문자열 buf 에 출력 ('\0' 이 추가됨) Returns: number of characters stored in array 46

vprintf() vfprintf() vsprintf() #include <stdarg.h> #include <stdio.h> int vprintf (const char *format, va_list arg ); int vfprintf (FILE *fp, const char *format, va_list arg ); int vsprintf (char *buf,const char *format, va_list arg ); 가변 인자 리스트(variable length argument lists)를 va_list args 로 전달 47

scanf() fscanf() sscanf() #include <stdio.h> int scanf (const char *format, ); int fscanf (FILE *fp, const char *format, ); int sscanf (const char *buf,const char *format, ); scanf() 표준 입력에서 입력 fscanf() 스트림 fp 에서 입력 sscanf() 문자열 buf 에서 입력 Return: number of input items assigned, EOF if input error or end of file before any conversion 48

9. Temporary Files #include <stdio.h> char *tmpnam(char *ptr); FILE *tmpfile (void ); char *tempnam(const char *directory,const char *prefix ); tmpnam() : 임시파일이름 생성 L_tmpnam : 파일 이름의 최대 길이 상수 (stdio.h> if ptr!= NULL: ptr 에 이름 저장하고 ptr 리턴 if ptr == NULL: 라이브러리 내부 static 변수에 이름 저장하고 주소 리턴 tmpfile() : "wb+" 로 임시파일을 생성하고 스트림 포인터 리턴 tempnam() : 만들어질 임시 파일 이름의 경로와 접두어를 지정 49

고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 5장. 고급 입출력 (Advanced I/O) 2004. 08. 22 1

Contents 1. Nonblocking I/O 2. Record Locking 3. I/O Multiplexing 4. Asynchronous I/O 5. Memory Mapped I/O 2

1. Nonblocking I/O Blocking I/O I/O 작업이 완료되기를 기다리며 영원히 리턴안할 수 있다 (block forever) 예) getchar() 은 엔터키를 입력할 때까지 영원히 기다린다 Nonblocking I/O I/O 작업이 당장 완료될 수 없으면 곧장 에러를 리턴한다 예) 이미 입력된 키가 있으면 그 값을 리턴하고, 아니면 기다리지 않고 즉시 에러를 리턴한다 주의: Asynchronous I/O 와 혼동하지 말라 3

Slow system calls which can block forever Reads from pipes, terminals, network devices, if data isn't present Writes to above if they don't handle reading promptly Opens of files block until some condition occurs Open of a terminal device attached to a modem Open of a FIFO for writing only when there is no other process for reading the FIFO Reads and writes of files that have mandatory record locking enabled Certain ioctl operations Some of IPC functions 4