컴퓨터특강 () [Ch. 3] 2006 년봄학기 문양세강원대학교컴퓨터과학과 강의목표및내용 강의목표 파일의특성을이해한다. 파일을열고닫는다. 파일로부터데이터를읽고쓴다. 기타파일제어함수를익힌다. 강의내용 파일구조 (UNIX 파일은어떤구조일까?) 파일관련시스템호출 시스템호출의효율과구조 Page 2 1
What is a File? A file is a contiguous sequence of bytes. (UNIX 에서파일은연속적인바이트시퀀스로볼수있다.) No format imposed by the operating system. (UNIX 운영체제는파일에특별한 Format 을부여치않는다.) Each byte is individually addressable in a disk file. ( 파일의각바이트는고유의주소를가지고 ( 매길수 ) 있다.) Page 3 File Descriptor (1/2) open() returns a fd, an integer value. Used in subsequent I/O operations on that file. (Open 된파일의 fd 는이후 File I/O 연산에사용된다.) close(fd) closes that file described by fd. All of a process's open files are automatically closed when it terminates. ( 프로세스가종료되면, 해당프로세스가 Open 한파일은자동적으로 Close 된다.) Page 4 2
File Descriptor (2/2) file descriptor: 0 ~ N (N = 19? or more) // unistd.h Value 0 1 2 3.. 19 Meaning standard input standard output standard error fds for users Page 5 파일을위한 Kernel 자료구조 process table entry file descriptors fd 0: fd 1: fd 2: fd 3: fd flags ptr.... open 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 The meaning of each field will be explained in next slides. Page 6 3
Process Table Entry 프로세스테이블 (Process Table) 커널 (kernel) 자료구조 프로세스목록 프로세스 프로세스테이블항목 프로세스테이블항목 (Process Table Entry) 파일구분자 (file descriptor) 의배열을포함 Page 7 Open File Table 파일테이블 (File Table) 커널자료구조 열려진모든파일목록 열려진파일 파일테이블의항목 파일테이블항목 (File Table Entry) 파일상태플래그 (read, write, append, sync, nonblocking, ) open() 시주는정보 파일의현재위치 (current file offset) v-node에대한포인터 Page 8 4
v-node v-node 의내부 파일의유형 ( 일반, 디렉토리, 특수파일, ) 함수들에대한포인터배열 : 이파일을다루는데사용되는함수들 i-node 하드디스크에저장되어있는자료구조 파일에대한 ( 실질적인 ) 정보를가지고있음 소유자, 크기 파일이위치한장치 ( 실제가장중요한정보에해당함 ) 파일내용디스크블럭에대한포인터 ( 실제가장중요한정보에해당함 ) Page 9 파일관련 System Calls open() 열기 creat() - 파일생성 close() read() 닫기 읽기 write() 쓰기 lseek() - 이동 Page 10 5
open() 파일열기 #include <sys/types.h> #include <sys/stat.h> int open (const char *pathname, int oflag, [ mode_t mode ]); 파일을연다. 파일이없으면경우에따라새로만들어질수도있다. pathname mode : 파일의이름 : 파일의 access permission 값으로, 생략가능새로운파일을만드는경우에만사용됨 (creat() 함수설명참조 ) 리턴값 : 파일식별자 (file descriptor), 실패하면 -1 Page 11 open() 의파라미터 (1/2) 두번째파라미터 oflag 는다음상수들의 (logical) OR 이다. 예 int fd; fd = open("afile", O_RDWR O_CREAT, 0644); 열기모드에대해서, 반드시하나를지정해주어야한다. O_RDONLY : 읽기모드, write 함수를사용할수없음 O_WRONLY : 쓰기모드, read 함수를사용할수없음 O_RDWR : 읽고쓰기모드, read 및 write 사용가능 Page 12 6
open() 의파라미터 (2/2) 선택적지정가능플래그 O_APPEND : 모든 write 된데이터는파일의끝에추가된다. O_CREAT : 파일이없을경우파일을생성한다 ( 이경우, 세번째인자mode가사용 ). O_EXCL : 그이름의파일이이미있고 O_CREAT를지정한경우에러를발생시킨다. O_TRUNC : 파일이있는경우에기존내용을지우고, 파일크기를 0으로만든다. O_SYNC : 각 write 함수호출은디스크에물리적으로쓰여진후리턴한다 Page 13 예제 : open.c /* open.c */ #include <stdlib.h> #include <unistd.h> int main() { int filedes; char fname[] = "afile"; } if ((filedes = open (fname, O_RDWR)) == -1) perror(fname); else { printf("%s is opened.\n", fname); close(filedes); } return 0; Page 14 7
creat() 파일생성 #include <sys/types.h> #include <sys/stat.h> int creat ( const char *pathname, mode_t mode ); 새로운파일을생성한다. pathname mode : 파일의이름 : 파일의 access permission 값 리턴값 : 파일식별자 (file descriptor), 실패하면 -1 Page 15 creat() 의파라미터 다음두함수의호출은동일한기능을수행함 fd = creat ( pathname, mode ); fd = open ( pathname, O_WRONLY O_CREAT O_TRUNC, mode); 두번째파라미터인 mode 는 permission mode 를나타냄 0644 -rw-r--r-- 0755 -rwxr-xr-x 0444 -r--r--r-- Page 16 8
close() 파일닫기 #include <sys/types.h> #include <sys/stat.h> int close ( int filedesc ); 작업이끝난후파일을닫는다. 파일을닫지않더라도프로세스가종료하면, 모든열려진파일들은자동적으로닫힌다. filedesc : 닫고자하는파일의파일식별자 (File Descriptor) 리턴값 : 파일식별자 (file descriptor), 실패하면 -1 Page 17 read() 파일읽기 (1/2) #include <unistd.h> ssize_t read ( int filedes, void *buf, size_t nbytes ); 파일에서데이터를읽는다. buf: 읽은데이터를저장할메모리 ( 버퍼 ) nbytes: 읽을데이터의바이트수리턴값 성공하면읽은바이트수 (nbytes와다를수( 작을수 ) 있음 ) 파일의끝을만나면 0 실패하면 -1 Page 18 9
read() 파일읽기 (2/2) 읽을데이터가충분하면한번에 nbytes 만큼읽는다. 읽을데이터가 nbytes 보다적은경우더적게읽기도한다. 파일의끝에다다른경우 네트웍입출력을수행하는경우 참고 size_t : unsigned integer ssize_t : signed integer Page 19 예제 : count.c ( 문자수세는프로그램 ) #include <stdlib.h> // count.c #include <unistd.h> #define BUFSIZE 512 int main() { char buffer[bufsize]; int filedes; ssize_t nread; long total = 0; } if ((filedes = open("afile", O_RDONLY)) == -1) { perror("afile"); exit(-1); } /* 파일의끝에도달할때까지반복 */ while( (nread = read(filedes, buffer, BUFSIZE)) > 0) total += nread; close(filedes); printf ("total chars in afile: %ld\n", total); return 0; Page 20 10
write() 파일쓰기 #include <unistd.h> ssize_t write (int filedes, const void *buf, size_t nbytes); 파일에데이터를쓴다. buf: 쓸데이터를저장한메모리 ( 버퍼 ) nbytes: 쓸데이터의바이트수리턴값 성공하면, 파일에쓰여진데이터의바이트수 (nbytes보다작을수있음 ) 실패하면 -1 Page 21 lseek() 오프셋 ( 커서 ) 이동 (1/2) #include <sys/types.h> #include <unistd.h> off_t lseek (int filedes, off_t offset, int whence ); 파일의현재위치 (current file offset) 를이동한다. 파라미터설명 whence: ( 이동을시작할 ) 위치의기준점 SEEK_SET : 파일의시작점을기준으로이동 SEEK_CUR : 현재위치를기준으로이동 SEEK_END : 파일의끝을기준으로이동 offset: 기준점에서의상대적인거리 (byte 단위 ) SEEK_CUR, SEEK_END 와같이쓰일때는음수도가능 리턴값 : 성공하면이동한현재위치를리턴, 실패하면 -1 Page 22 11
lseek() 오프셋 ( 커서 ) 이동 (2/2) 파일의현재위치 ( 오프셋 ) 를임의의위치로이동한다 파일의현재위치 (current file offset) 파일에대한읽기 / 쓰기는파일의현재위치에서실행된다. 파일을처음열면현재위치는 0, 즉파일의시작이다. 읽기 / 쓰기후파일의현재위치는읽기 / 쓰기한 byte 수만큼저절로뒤로이동된다. lseek() 를사용하여임의의위치로파일의현재위치를이동할수있다 Page 23 예제 : lseek1.c (1/2) #include <unistd.h> /* lseek1.c */ char buf1[] = "abcdefghij"; char buf2[] = "ABCDEFGHIJ"; int main() { int fd; if ( (fd = creat("file.hole", 0644)) < 0) { perror("file.hole"); exit(-1); } if (write(fd, buf1, 10)!= 10) /* offset now = 10 */ perror("buf1"); if (lseek(fd, 40, SEEK_SET) == -1) /* offset now = 40 */ perror("lseek"); if (write(fd, buf2, 10)!= 10) /* offset now = 50 */ perror("buf2"); return 0; } Page 24 12
예제 : lseek1.c (2/2) lseek1.c 의출력파일 file.hole 의내용 0 10 20 30 40 0 a A 1 b B 2 c C 3 d D 4 e E 5 f F 6 g G 7 h H 8 i I 9 j J UNIX 명령어인 od (octal dump) 를사용하여확인할수있음 Page 25 fcntl() 파일제어 #include <sys/types.h> #include <unistd.h> int fcntl (int filedes, int cmd, /* int arg */ ); 역할 : 파일의속성을알아내거나변경한다. cmd: F_GETFL, F_SETFL, F_GETFD, F_SETFD, F_DUPFD, 리턴값 성공인경우 : 파라미터인 cmd에따라다름 실패인경우 : -1 Page 26 13
fcntl() 의주요사용법 F_GETFL : file table 의 file status flags 를리턴 F_SETFL : 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) Page 27 예제 : fileflags.c #include <sys/types.h> // fileflags.c int main() { int accmode, val; int fd; fd = open("afile", O_WRONLY O_APPEND); if (fd == -1) perror("afile"); if ((val = fcntl(fd, F_GETFL, 0)) < 0) { perror("fcntl"); exit(-1); } 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; } Page 28 14
Asynchronous Write UNIX 에서의 Write 는 Asynchronous Write 이다. 데이터가디스크에쓰여지길기다리지않고, 쓰여질데이터를큐 (queue) 에등록하고바로리턴한다. 큐에등록된데이터는나중에 (Scheduling에의해한꺼번에 ) 디스크에쓰여진다 Synchronous Write Write 호출은데이터가실제로디스크에쓰여진후리턴한다. Asynchronous Write에비해서Clock Time이증가한다. File Table 의 File Status Flags 에서 O_SYNC 플래그를설정한다. Page 29 예제 : write2.c (1/2) #include <sys/types.h> // write2.c #include <sys/stat.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"); } Page 30 15
예제 : write2.c (2/2) int main() { int i, fd; char buf[buffsize]; memset(buf, '.', BUFFSIZE); if ((fd = creat("file.write", 0600)) < 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; } Page 31 실험결과 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 가훨씬더느림 DBMS(Database Management System) 처럼실제로데이터가디스크에기록되었는지여부가중요한경우에사용됨 Page 32 16
에러처리 파라미터 errno 값에해당하는에러메시지를리턴한다. #include <stdio.h> void perror(const char *msg); 표준에러에다음과같은순서로메시지를출력한다. msg 출력 문자열 ": " 출력 시스템전역변수 (system global variable) errno 값에해당하는에러메시지출력 Page 33 17