Top Banner
11 11 장 장장 장 장장 1
53

11 장 파일

Jan 04, 2016

Download

Documents

joy-daugherty

11 장 파일. 11.1 시스템 호출. 유닉스 / 리눅스 커널 (kernel). 하드웨어를 운영 관리하여 다음과 같은 서비스를 제공 프로세스 관리 (Process management) 파일 관리 (File management) 메모리 관리 (Memory management) 통신 관리 (Communication management) 주변장치 관리 (Device management). 시스템 호출 (system call). 시스템 호출은 유닉스 / 리눅스 커널에 서비스를 요청하기 위한 프로그래밍 인터페이스 - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 11 장 파일

1111 장 파일장 파일

1

Page 2: 11 장 파일

11.1 11.1 시스템 호출 시스템 호출

2

Page 3: 11 장 파일

유닉스유닉스 //리눅스 커널리눅스 커널 (kernel)(kernel) 하드웨어를 운영 관리하여 다음과 같은 서비스를 제공

프로세스 관리 (Process management) 파일 관리 (File management) 메모리 관리 (Memory management) 통신 관리 (Communication management) 주변장치 관리 (Device management)

3

Page 4: 11 장 파일

시스템 호출시스템 호출 (system call)(system call) 시스템 호출은 유닉스 /리눅스 커널에 서비스를 요청하기 위한

프로그래밍 인터페이스 응용 프로그램은 시스템 호출을 통해서 유닉스 /리눅스 커널에

서비스를 요청한다 /usr/include/asm/unistd_32.h 참조

4

Page 5: 11 장 파일

11.2 11.2 파일파일

5

Page 6: 11 장 파일

유닉스유닉스 //리눅스에서 파일리눅스에서 파일 연속된 바이트의 나열 특별한 다른 포맷을 정하지 않음 디스크 파일뿐만 아니라 외부 장치에 대한 인터페이스

6

Page 7: 11 장 파일

파일 열기파일 열기 : open(): open() 파일을 사용하기 위해서는 먼저 open() 시스템 호출을

이용하여 파일을 열어야 한다

파일 디스크립터는 열린 파일을 나타내는 번호 oflag, mode : 교재 331~332 쪽 ,

/usr/include/bits/fcntl.h 참조

7

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

int open (const char *path, int oflag, [ mode_t mode ]);

파일 열기에 성공하면 파일 디스크립터를 리턴 , 실패하면 -1 을 리턴

Page 8: 11 장 파일

파일 열기파일 열기 : : 예예 fd = open("account",O_RDONLY);

fd = open(argv[1], O_RDWR);

fd = open(argv[1], O_RDWR | O_CREAT, 0600);

fd = open("tmpfile", O_WRONLY|O_CREAT|O_TRUNC, 0600);

fd = open("/sys/log", O_WRONLY|O_APPEND|O_CREAT, 0600);

if ((fd = open("tmpfile", O_WRONLY|O_CREAT|O_EXCL, 0666))==-1)

8

Page 9: 11 장 파일

fopen.cfopen.c#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <errno.h>int main(int argc, char *argv[]){ int fd; if ((fd = open(argv[1], O_RDWR)) == -1) perror(argv[1]); printf(" 파일 %s 열기 성공 \n", argv[1]); close(fd); exit(0);}

9

① fd 번호를 출력해보세요 !② 매개변수 없을 경우도 잘 처리하도록 debug 해보세요 !

Page 10: 11 장 파일

파일 생성파일 생성 : creat(): creat() creat() 시스템 호출

path 가 나타내는 파일을 생성하고 쓰기 전용으로 연다 생성된 파일의 사용권한은 mode 로 정한다 기존 파일이 있는 경우에는 그 내용을 삭제하고 연다 다음 시스템 호출과 동일

open(path, WRONLY | O_CREAT | O_TRUNC, mode);

10

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

int creat (const char *path, mode_t mode );

파일 생성에 성공하면 생성된 파일의 파일 디스크립터 , 실패하면 -1 을 리턴

Page 11: 11 장 파일

파일 닫기파일 닫기 : close(): close() close() 시스템 호출은 fd 가 나타내는 파일을 닫는다

11

#include <unistd.h>

int close( int fd );

fd 가 나타내는 파일을 닫는다 . 성공하면 0, 실패하면 -1 을 리턴한다 .

Page 12: 11 장 파일

데이터 읽기데이터 읽기 : read(): read() read() 시스템 호출

fd 가 나타내는 파일에서 nbytes 만큼의 데이터를 읽고 읽은 데이터는 buf 에 저장한다

12

#include <unistd.h>

ssize_t read ( int fd, void *buf, size_t nbytes );

파일 읽기에 성공하면 읽은 바이트 수 , 파일 끝을 만나면 0, 실패하면 -1 을

리턴

Page 13: 11 장 파일

fsize.cfsize.c#include <stdio.h>#include <stdlib.h>#include <fcntl.h>//#include <unistd.h>#define BUFSIZE 512/* 파일 크기를 계산한다 */int main(int argc, char *argv[]){ char buffer[BUFSIZE]; int fd; ssize_t nread; long total = 0; if ((fd = open(argv[1], O_RDONLY)) == -1) perror(argv[1]); /* 파일의 끝에 도달할 때까지 반복해서 읽으면서 파일 크기 계산 */ while((nread = read(fd, buffer, BUFSIZE)) > 0) total += nread; close(fd); printf ("%s 파일 크기 : %ld 바이트 \n", argv[1], total); exit(0);}

13

매개변수 없을 경우도 잘 처리하도록 debug 해보세요 !

$ gcc –o fsize fsize.c

$ fsize xx

Page 14: 11 장 파일

데이터 쓰기데이터 쓰기 : write(): write() write() 시스템 호출

buf 에 있는 nbytes 만큼의 데이터를 fd 가 나타내는 파일에 쓴다

14

#include <unistd.h>

ssize_t write (int fd, void *buf, size_t nbytes);

파일에 쓰기를 성공하면 실제 쓰여진 데이터의 바이트 수를 리턴하고 ,

실패하면 -1 을 리턴

Page 15: 11 장 파일

fcp.cfcp.c#include <stdio.h>#include <stdlib.h>#include <fcntl.h>/* 파일 복사 프로그램 */main(int argc, char *argv[]){ int fd1, fd2, n; char buf[BUFSIZ]; if (argc != 3) { fprintf(stderr," 사용법 : %s file1 file2\n", argv[0]); exit(1); } if ((fd1 = open(argv[1], O_RDONLY)) == -1) { perror(argv[1]); exit(2); } if ((fd2 = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) { perror(argv[2]); exit(3); } while ((n = read(fd1, buf, BUFSIZ)) > 0) write(fd2, buf, n); // 읽은 내용을 쓴다 exit(0); }15

O_APPEND

BUFSIZ 값 출력해보기$ grep BUFSIZ /usr/include/*

Page 16: 11 장 파일

(( 보충보충 ) $ man) $ man$ man read$ whatis read$ man –f read (Unix) $ man –l readread (1p) - read a line from standard inputread (2) - read from a file descriptorread (3p) - read from a fileread [builtins] (1) - bash built-in commands, see bash(1)$ man –s 2 read 또는 $ man 2 read$ man –M /usr/share/man 2 read ( 목록의 man page 가 나오지 않을

경우 )$ man man

16

1 Executable programs or shell commands2 System calls (functions provided by the kernel)3 Library calls (functions within program libraries)4 Special files (usually found in /dev)5 File formats and conventions eg /etc/passwd6 Games7 Miscellaneous (including macro packages and conven-tions8 System administration commands (usually only for root)9 Kernel routines [Non standard]

1 절 명령어2 절 시스템 호출3 절 라이브러리 함수4 절 특수화일5 절 파일 형식6 절 게임7 절 기타 정보8 절 유지보수 명령어9 절 커널 루틴

Page 17: 11 장 파일

(( 보충보충 ) set-user-id set-group-id set-) set-user-id set-group-id set-sticky-bitsticky-bit Symbolic File Access Modes

$ chmod a=rw xx$ chmod g+x xx$ chmod g-rwx xx$ chmod g=u xx

Octal File Access Modes$ chmod 644 xx$ chmod 751 xx$ chmod 000 xx

실행파일에 대하여 4000 set user ID : $ chmod 4751 xx $ chmod u+s myfile 2000 set group ID : $ chmod 2751 xx $ chmod g+s myfile 1000 set sticky bit : $ chmod 1751 xx $ chmod o+t myfile$ find / -perm -4755 -ls > result $ find / -perm -4700 -ls > result

디렉터리에 대하여 1000 set sticky bit : $ chmod 1777 /share 그 디렉터리 안의 파일 제거 또는 이름 변경은 파일 소유자 , 디렉터리 소유자 , 수퍼유저만

가능 디렉터리 소유자 아닌 다른 사용자는 그 안에 자기파일 생성만 가능

umask (user mask) : file 생성시 허가권 제한17

- rws r-x --x- 100 111 101 001

- rwx r-s --x- 010 111 101 001

- rwx r-x --t- 001 111 101 001

Page 18: 11 장 파일

(( 보충보충 ) IA-32) IA-32(Intel Architecture, 32-bit)(Intel Architecture, 32-bit) 정수 정수 표현표현 Q:IA-32(Intel Architecture, 32-bit) 정수형 데이터 음수 표현 방법은 ?

signed & unsigned char(8bit), short(16bit), int(32bit), long(64bit), long long(128bit)

리틀 엔디안 (Little-Endian) 사용 고정 소수점 (Fixed-Point) 표현

첫 번째 비트는 부호 비트 양수 (+) 는 0, 음수 (-) 는 1 로 표시 나머지는 정수부가 저장되고 , 소수점은 맨 오른쪽에 있는 것으로 가정

고정 소수점 음수 표현 방법 부호와 절대치 (signed-magnitude) 양수 표현에 대하여 부호 비트만 1 로 변경 1 의 보수 (1’s complement) 양수 표현에 대하여 1 의 보수 계산 2 의 보수 (2’s complement) 양수 표현에 대하여 2 의 보수 계산 (reverse+1)

( 예 ) short score = 99; 99 = 6*16 + 3 = 0x63 0000 0000 0110 0011

( 예 ) short score = -99; -99 = -6*16 - 3 = -0x63 ( 부호와 절대치 ) 1000 0000 0110 0011 (2 의 보수 ) 1111 1111 1001 1101

18

Page 19: 11 장 파일

(( 보충보충 ) ) 비트단위 정수 출력 비트단위 정수 출력 bitwise.cbitwise.c#include <stdio.h>#include <limits.h>void bit_print(short);main(int arc, char *argv[]){ short i=atoi(argv[1]), mask=1; bit_print(i); printf("\n 정수 : %d\n", i);}void bit_print(short a){ int i; int n=sizeof(short) * CHAR_BIT; /* /usr/include/limits.h 55 행 */ printf("n=%d, sizeof(short)=%d, CHAR_BIT=%d\n", n, sizeof(short), CHAR_BIT); int mask = 1 << (n-1); for (i=1; i<=n; ++i) { putchar(((a & mask) == 0) ? '0' : '1'); a <<= 1; if(i % (CHAR_BIT/2) == 0 && i < n) putchar(' '); }}

19

① short 형을 int 형으로 수정하세요 !② 매개변수 없을 경우도 잘 처리하도록 debug 하세요 !

$ gcc –o bitwise bitwise.c

$ bitwise -99

Page 20: 11 장 파일

11.3 11.3 현재 파일 위치 현재 파일 위치

20

Page 21: 11 장 파일

파일 위치 포인터파일 위치 포인터 (file position (file position pointer)pointer) 파일 위치 포인터는 파일 내에 읽거나 쓸 위치인 현재 파일

위치 (current file position) 를 가리킨다 .

21

Page 22: 11 장 파일

파일 위치 포인터 이동파일 위치 포인터 이동 : lseek(): lseek() lseek() 시스템 호출

임의의 위치로 파일 위치 포인터를 이동시킬 수 있다 .

22

#include <unistd.h>

off_t lseek (int fd, off_t offset, int whence );

이동에 성공하면 현재 위치를 리턴하고 실패하면 -1 을 리턴한다 .

Page 23: 11 장 파일

파일 위치 포인터이동파일 위치 포인터이동 : : 예예 파일 위치 이동

lseek(fd, 0L, SEEK_SET); 파일 시작으로 이동 (rewind) lseek(fd, 100L, SEEK_SET); 파일 시작에서 100 바이트

위치로 lseek(fd, 0L, SEEK_END); 파일 끝으로 이동 (append)

레코드 단위로 이동 lseek(fd, n * sizeof(record), SEEK_SET); n+1 번째 레코드 시작위치로 lseek(fd, sizeof(record), SEEK_CUR); 다음 레코드 시작위치로 lseek(fd, -sizeof(record), SEEK_CUR); 전 레코드 시작위치로

파일끝 이후로 이동 lseek(fd, sizeof(record), SEEK_END); 파일끝에서 한 레코드 다음

위치로

23

Page 24: 11 장 파일

레코드 저장 예레코드 저장 예 write(fd, &record1, sizeof(record)); write(fd, &record2, sizeof(record)); lseek(fd, sizeof(record), SEEK_END); write(fd, &record3, sizeof(record));

24

레코드 레코드 레코드

$ vi $ vi student.hstudent.h

#define MAX 20

struct student {

int id;

char name[MAX];

int score;

};

Page 25: 11 장 파일

dbcreate.cdbcreate.c#include <stdio.h>

#include <stdlib.h>

#include <fcntl.h>

#include "student.h"

#define START_ID 1201001

/* 학생 정보를 입력받아 데이터베이스 파일에 저장한다 */

int main(int argc, char *argv[])

{

int fd;

struct student record;

if (argc < 2) {

fprintf(stderr, " 사용법 : %s file\n", argv[0]);

exit(1);

}

25

if ((fd = open(argv[1], O_WRONLY | O_CREAT | O_EXCL, 0640)) == -1) {

perror(argv[1]);

exit(2);

}

printf("%7s %6s %4s\n", " 학번 ", "이름 ", " 점수 ");

while (scanf("%d %s %d", &record.id, record.name, &record.score) == 3) {

lseek(fd, (record.id - START_ID) * sizeof(record), SEEK_SET);

write(fd, (char *) &record, sizeof(record) );

}

close(fd);

exit(0);

}$ gcc –o dbcreate.c dbcreate.c

$ dbcreate stdb

Page 26: 11 장 파일

dbquery.cdbquery.c#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include "student.h"#define START_ID 1201001/* 학번을 입력받아 해당 학생의 레코드를 파일에서

읽어 출력한다 */int main(int argc, char *argv[]){ int fd, id; char c; struct student record; if (argc < 2) { fprintf(stderr, " 사용법 : %s file\n",

argv[0]); exit(1); } if ((fd = open(argv[1], O_RDONLY)) == -1) { perror(argv[1]); exit(2); }

26

do { printf(" 검색할 학생의 학번 입력 : "); if (scanf("%d", &id) == 1) { lseek(fd, (id-START_ID)*sizeof(record),

SEEK_SET); if ((read(fd, (char *) &record, sizeof(record))

> 0) && (record.id != 0)) printf(" 이름 :%s\t 학번 :%d\t 점수 :%d\n",

record.name, record.id, record.score); else printf(" 레코드 %d 없음 \n", id); } else printf(" 입력 오류 "); printf(" 계속하겠습니까 ?(Y/N) "); scanf(" %c", &c); } while (c=='Y'); close(fd); exit(0);}

$ gcc –o dbquery.c dbquery.c

$ dbcreate stdb

Page 27: 11 장 파일

레코드 수정레코드 수정 과정과정(1) 파일로부터 해당 레코드를 읽어서 (2) 이 레코드를 수정한 후에(3) 수정된 레코드를 다시 파일 내의 원래 위치에 써야 한다

27

Page 28: 11 장 파일

dbupdate.cdbupdate.c#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include "student.h"#define START_ID 1201001/* 학번을 입력받아 해당 학생 레코드를 수정한다 */int main(int argc, char *argv[]){ int fd, id; char c; struct student record; if (argc < 2) { fprintf(stderr, " 사용법 : %s file\n", argv[0]); exit(1); } if ((fd = open(argv[1], O_RDWR)) == -1) { perror(argv[1]); exit(2); }

28

do { printf(" 수정할 학생의 학번 입력 : "); if (scanf("%d", &id) == 1) { lseek(fd, (long) (id-

START_ID)*sizeof(record), SEEK_SET); if ((read(fd, (char *) &record, sizeof(record))

> 0) && (record.id != 0)) { printf(" 학번 :%8d\t 이름 :%4s\t 점수 :%4d\

n", record.id, record.name,

record.score); printf(" 새로운 점수 : "); scanf("%d", &record.score); lseek(fd, (long) -sizeof(record),

SEEK_CUR); write(fd, (char *) &record, sizeof(record)); } else printf(" 레코드 %d 없음 \n", id); } else printf(" 입력오류 \n"); printf(" 계속하겠습니까 ?(Y/N)"); scanf(" %c",&c); } while (c == 'Y'); close(fd); exit(0);}

$ gcc –o dbupdate.c dbupdate.c

$ dbupdate stdb

Page 29: 11 장 파일

11.4 11.4 파일 상태 정보파일 상태 정보

29

Page 30: 11 장 파일

파일 상태파일 상태 (file status)(file status) 파일 상태

파일에 대한 모든 정보 블록수 , 파일 타입 , 접근 권한 , 링크수 , 파일 소유자의 사용자 ID, 그룹 ID, 파일 크기 , 최종 수정 시간 등

예$ ls -sl hello

2 -rw-r--r-- 1 mysung other 617 11 월 26 일 15:59 hello.c

블록수 사용권한 링크수 사용자 ID 그룹 ID 파일크기 최종 수정 시간 파일이름

파일 타입

30

Linux: $ getconf PAGESIZE 또는 PAGE_SIZE (4096)Solaris: $ pagesize –a (4096, 2097152)

Page 31: 11 장 파일

상태 정보상태 정보 : stat(): stat() 파일 하나당 하나의 i- 노드가 있으며 i- 노드 내에 파일에 대한 모든 상태 정보가 저장되어 있다Q: stat() 과 lstat() 의 차이점은 ? $ man –s 2 stat

31

#include <sys/types.h>

#include <sys/stat.h>

int stat (const char *pathname, struct stat *buf);

int fstat (int fd, struct stat *buf);

int lstat (const char *pathname, struct stat *buf);

파일의 상태 정보를 가져와서 stat 구조체 buf 에

저장한다 . 성공하면 0, 실패하면 -1 을 리턴한다 .

Page 32: 11 장 파일

stat stat 구조체구조체

32

/usr/include/sys/stat.h 107 행 /usr/include/bits/stat.h 39 행 참조struct stat{ dev_t st_dev; /* 장치 */ ino_t st_ino; /* inode 번호 */ mode_t st_mode; /* 파일타입과 사용권한 */ nlink_t st_nlink; /* 하드 링크 수 */ uid_t st_uid; /* 소유자의 사용자 ID */ gid_t st_gid; /* 소유자의 그룹 ID */ dev_t st_rdev; /* 장치이면 장치 번호 */ off_t st_size; /* 파일의 바이트 크기 */ unsigned long st_blksize; /* 파일시스템 I/O 최적 블록 크기 */ unsigned long st_blocks; /* 파일에 할당 된 512-byte 블록 수

*/ time_t st_atime; /* 최종 접근 시간 */ time_t st_mtime; /* 최종 수정 시간 */ time_t st_ctime; /* 최종 상태 변경 시간 */};

Page 33: 11 장 파일

파일 타입과 매크로 함수파일 타입과 매크로 함수

33

파일 타입 설명 파일 타입을 검사하기 위한 매크로 함수

일반 파일 데이터를 갖고 있는 텍스트 파일 또는 이진 파일 S_ISREG()

디렉터리 파일 파일의 이름들과 파일 정보에 대한 포인터를 포함하는 파일 S_ISDIR()

문자 장치 파일 문자 단위로 데이터를 전송하는 장치를 나타내는 파일 S_ISCHR()

블록 장치 파일 블록 단위로 데이터를 전송하는 장치를 나타내는 파일 S_ISBLK()

FIFO 파일 프로세스 간 통신에 사용되는 파일로 이름 있는 파이프 S_ISFIFO()

소켓 네트워크를 통한 프로세스 간 통신에 사용되는 파일 S_ISSOCK()

심볼릭 링크 다른 파일을 가리키는 포인터 역할을 하는 파일 S_ISLNK()

/usr/include/sys/stat.h 127 행 참조 /usr/include/bits/stat.h 142 행 참조

Page 34: 11 장 파일

ftype.cftype.c

#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>/* 파일 타입을 검사한다 . */int main(int argc, char *argv[]){ int i; struct stat buf; 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)) printf("%s\n", " 일반 파일 "); if (S_ISDIR(buf.st_mode)) printf("%s\n", " 디렉터리 "); if (S_ISCHR(buf.st_mode)) printf("%s\n", " 문자 장치 파일 "); if (S_ISBLK(buf.st_mode)) printf("%s\n", " 블록 장치 파일 "); if (S_ISFIFO(buf.st_mode)) printf("%s\n", "FIFO 파일 "); if (S_ISLNK(buf.st_mode)) printf("%s\n", " 심볼릭 링크 "); if (S_ISSOCK(buf.st_mode)) printf("%s\n", " 소켓 "); } exit(0);}

34

$ gcc –o ftype ftype.c

$ ln -s xx yy

$ ftype xx yy

$ ftype *

$ ftype /dev/* | more

① st_ino 와 st_size 출력해 보세요 !

② Q: stat() 과 lstat() 의 차이점은 ?

Page 35: 11 장 파일

파일 상태 정보 변경파일 상태 정보 변경 chmod() 시스템 호출

파일의 상태 정보를 변경

35

#include <sys/types.h>

#include <sys/stat.h>

int chmod(const char *path, mode_t mode);

path 가 나타내는 파일의 사용권한을 mode 로 변경한다

Page 36: 11 장 파일

fchmod.cfchmod.c

#include <stdio.h>

#include <stdlib.h>

/* 파일 사용권한을 변경한다 */

main(int argc, char *argv[])

{

long int strtol( );

int newmode;

newmode = (int) strtol(argv[1],(char **) NULL, 8);

if (chmod(argv[2], newmode) == -1) {

perror(argv[2]);

exit(1);

}

exit(0);

}

36

# include <sys/types.h> /usr/include/stdlib.h 320 행typedef __mode_t mode_t; /usr/include/sys/types.h 71 행# define __STD_TYPE typedef /usr/include/bits/types.h 127 행__STD_TYPE __MODE_T_TYPE __mode_t; /usr/include/bits/types.h 139 행#include <bits/typesizes.h> /usr/include/bits/types.h 131 행#define __MODE_T_TYPE __U32_TYPE /usr/include/bits/typesizes.h 35 행#define __U32_TYPE unsigned int /usr/include/bits/types.h 102 행

$ gcc –o fchmod fchmod.c$ fchmod 666 xx$ ls –asl xx

$ man atoiint atoi(const char *nptr);= strtol(nptr, (char **)NULL, 10);

Page 37: 11 장 파일

11.5 11.5 디렉터리디렉터리

37

Page 38: 11 장 파일

디렉터리 구현디렉터리 구현 디렉터리 내에는 무엇이 저장되어 있을까 ? 디렉터리 엔트리

#include <dirent.h> /usr/include/dirent.h 30 행 #include <bits/dirent.h> /usr/include/bits/dirent.h 23 행struct dirent {#ifndef __USE_FILE_OFFSET64 __ino_t d_ino; __off_t d_off;#else __ino64_t d_ino; __off64_t d_off;#endif unsigned short int d_reclen; unsigned char d_type; char d_name[256]; /* We must not include limits.h! */ };38

DIR

Page 39: 11 장 파일

디렉터리 리스트디렉터리 리스트 opendir()

디렉터리 열기 함수 DIR 포인터 ( 열린 디렉터리를 가리키는 포인터 ) 리턴

readdir() 디렉터리 읽기 함수

39

#include <sys/types.h>

#include <dirent.h>

DIR *opendir (const char *path);

path 디렉터리를 열고 성공하면 DIR 구조체 포인터를 , 실패하면 NULL 을

리턴한다 .

struct dirent *readdir(DIR *dp);

한 번에 디렉터리 엔트리를 하나씩 읽어서 리턴한다 . typedef struct __dirstream DIR; /usr/include/dirent.h 128 행

Page 40: 11 장 파일

list1.clist1.c#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#include <stdio.h>#include <stdlib.h>/* 디렉터리 내의 파일 이름들을 리스트한다 */int main(int argc, char **argv){ DIR *dp; char *dir; struct dirent *d; struct stat st; char path[BUFSIZ+1]; if (argc == 1) dir = "."; // 현재 디렉터리를 대상으로 else dir = argv[1]; if ((dp = opendir(dir)) == NULL) // 디렉터리 열기 perror(dir); while ((d = readdir(dp)) != NULL) // 각 디렉터리 엔트리에 대해 printf("%s \n", d->d_name); // 파일 이름 프린트 closedir(dp); exit(0);}

40

$ gcc –o list1 list1.c$ list1$ list1 /usr

Page 41: 11 장 파일

파일 이름파일 이름 //크기 프린트크기 프린트 디렉터리 내에 있는 파일 이름과 그 파일의 크기 ( 블록의 수 ) 를

프린트하도록 확장

while ((d = readdir(dp)) != NULL) { // 디렉터리 내의 각 파일 sprintf(path, "%s/%s", dir, d->d_name); // 파일경로명 만들기 if (lstat(path, &st) < 0) // 파일 상태 정보

가져오기 perror(path);

printf("%5d %s", st->st_blocks, d->name); // 블록 수 , 파일 이름 출력

putchar('\n');

}

41

Page 42: 11 장 파일

디렉터리 리스트디렉터리 리스트 : : 예예 list2.c

ls –l 명령어처럼 파일의 모든 상태 정보를 프린트

프로그램 구성 main() 메인 프로그램 printStat() 파일 상태 정보 프린트 type() 파일 타입 리턴 perm() 파일 접근권한 리턴

42

Linux: $ getconf PAGESIZE 또는 PAGE_SIZE (4096)Solaris: $ pagesize –a (4096, 2097152)

Q: 한 블록의 크기는 ?

Page 43: 11 장 파일

list2.clist2.c

#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#include <pwd.h>#include <grp.h>#include <stdio.h>#include <stdlib.h>char type(mode_t);char *perm(mode_t);void printStat(char*, char*, struct stat*);int main(int argc, char **argv) /* 디렉터리 내용을 자세히 리스트한다 */{ DIR *dp; char *dir; struct stat st; struct dirent *d; char path[BUFSIZ+1]; if (argc == 1) dir = "."; else dir = argv[1]; if ((dp = opendir(dir)) == NULL) /* 디렉터리 열기 */ perror(dir); while ((d = readdir(dp)) != NULL) { /* 디렉터리의 각 파일에 대해

*/ sprintf(path, "%s/%s", dir, d->d_name); /* 파일경로명 만들기 */ if (lstat(path, &st) < 0) /* 파일 상태 정보 가져오기 */ perror(path); printStat(path, d->d_name, &st); /* 상태 정보 출력 */ putchar('\n'); } closedir(dp); exit(0);}

43

$ gcc –o list2 list2.c$ list2$ list2 | sort +9 -10$ ls -asl$ list2 /bin(/bin/su 파일로 확인 )

Page 44: 11 장 파일

list2.c (list2.c ( 계속계속 ))/* 파일 상태 정보를 출력 */void printStat(char *pathname, char *file, struct stat

*st) { printf("%5d ", st->st_blocks); printf("%c%s ", type(st->st_mode), perm(st-

>st_mode)); printf("%3d ", st->st_nlink); printf("%s %s ", getpwuid(st->st_uid)->pw_name,

getgrgid(st->st_gid)->gr_name); printf("%9d ", st->st_size); printf("%.12s ", ctime(&st->st_mtime)+4); printf("%s", file);} /* 파일 타입을 리턴 */char type(mode_t mode) { if (S_ISREG(mode)) return('-'); if (S_ISDIR(mode)) return('d'); if (S_ISCHR(mode)) return('c'); if (S_ISBLK(mode)) return('b'); if (S_ISLNK(mode)) return('l'); if (S_ISFIFO(mode)) return('p'); if (S_ISSOCK(mode)) return('s');}

44

char* perm(mode_t mode) { int i; static char perms[10] = "---------"; for (i=0; i < 3; i++) { if (mode & (S_IREAD >> i*3)) perms[i*3] = 'r'; if (mode & (S_IWRITE >> i*3)) perms[i*3+1] = 'w'; if (mode & (S_IEXEC >> i*3)) perms[i*3+2] = 'x'; } /* set user ID * * set group ID * * set sticky bit */ return(perms);}

/usr/include/bits/stat.h 161 행 참조 #define __S_ISUID 04000 /* Set user ID on execution. */#define __S_ISGID 02000 /* Set group ID on execution. */#define __S_ISVTX 01000 /* Save swapped text after use (sticky).#define __S_IREAD 0400 /* Read by owner. */#define __S_IWRITE 0200 /* Write by owner. */#define __S_IEXEC 0100 /* Execute by owner. */

① 교재 코드 Debug 채워 넣으세요

② st_ino 출력해 보세요③ Q: 파일시스템 I/O 최적 블록

크기는 ?

Page 45: 11 장 파일

디렉터리 만들기디렉터리 만들기 mkdir() 시스템 호출

path 가 나타내는 새로운 디렉터리를 만든다 "." 와 ".." 파일은 자동적으로 만들어진다

45

#include <sys/types.h>

#include <sys/stat.h>

int mkdir (const char *path, mode_t mode );

새로운 디렉터리 만들기에 성공하면 0, 실패하면 -1 을 리턴한다

Page 46: 11 장 파일

디렉터리 삭제디렉터리 삭제 rmdir() 시스템 호출

path 가 나타내는 디렉터리가 비어 있으면 삭제한다

46

#include <unistd.h>

int rmdir (const char *path);

디렉터리가 비어 있으면 삭제한다 . 성공하면 0, 실패하면 -1 을

리턴

Page 47: 11 장 파일

링크링크 링크는 기존 파일에 대한 또 다른 이름으로 하드 링크와 심볼릭 ( 소프트 ) 링크가 있다

47

#include <unistd.h>

int link(char *existing, char *new);

하드 링크를 만드는데 성공하면 0, 실패하면 -1 을 리턴한다

int unlink(char *path);

링크를 제거하는데 성공하면 0, 실패하면 -1 을 리턴한다

int symlink (const char *actualpath, const char *sympath );

심볼릭 링크를 만드는데 성공하면 0, 실패하면 -1 을 리턴한다

Page 48: 11 장 파일

링크의 구현링크의 구현 link() 시스템 호출

기존 파일 existing 에 대한 새로운 이름 new 즉 링크를 만든다

48

Page 49: 11 장 파일

하드 링크 하드 링크 vs vs 심볼릭 링크심볼릭 링크 하드 링크 (hard link)

지금까지 살펴본 링크 파일 시스템 내의 i- 노드를 가리키므로 같은 파일 시스템 내에서만 사용될 수 있다

심볼릭 링크 (symbolic link) 소프트 링크 (soft link) 실제 파일의 경로명 저장하고 있는 링크 파일에 대한 간접적인 포인터 역할을 한다 다른 파일 시스템에 있는 파일도 링크할 수 있다

49

Page 50: 11 장 파일

link.clink.c

#include <unistd.h>

#include <stdlib.h>

int main(int argc, char *argv[ ])

{

if (link(argv[1], argv[2]) == -1) {

exit(1);

}

exit(0);

}

50

Page 51: 11 장 파일

unlink.cunlink.c

#include <unistd.h>

#include <stdlib.h>

main(int argc, char *argv[ ])

{

int unlink( );

if (unlink(argv[1]) == -1) {

perror(argv[1]);

exit(1);

}

exit(0);

}

51

Page 52: 11 장 파일

slink.cslink.c

#include <unistd.h>

#include <stdlib.h>

int main(int argc, char *argv[ ])

{

if (symlink(argv[1], argv[2]) == -1) {

exit(1);

}

exit(0);

}

52

Page 53: 11 장 파일

핵심 개념핵심 개념 시스템 호출은 유닉스 커널에 서비스를 요청하기 위한 프로그래밍

인터페이스로 응용 프로그램은 시스템 호출을 통해서 유닉스 커널에 서비스를 요청한다

파일 디스크립터는 열린 파일을 나타낸다 파일 위치 포인터는 파일 내에 읽거나 쓸 위치인 현재 파일 위치를

가리킨다 파일 하나당 하나의 i- 노드가 있으며 i- 노드 내에 파일에 대한 모든

상태 정보가 저장되어 있다 디렉터리는 일련의 디렉터리 엔트리들을 포함하고 각 디렉터리

엔트리는 파일 이름과 그 파일의 i- 노드 번호로 구성된다 링크는 기존 파일에 대한 또 다른 이름으로 하드 링크와 심볼릭 (

소프트 ) 링크가 있다

53