제 3 장파일과디렉토리 숙대창병모 1
목표 파일시스템구현을이해한다. 파일의상태및구조를이해한다. 디렉토리구조및구현을이해한다. 숙대창병모 2
내용 1. 파일시스템구현 2. 파일상태 3. 파일접근허가권 4. 링크 5. 디렉토리 숙대창병모 3
3.1 파일시스템구현 숙대창병모 4
Inode (Index node) 한파일은하나의 i-node 를갖는다. 파일에대한모든정보를가지고있음 file type file size file permissions the owner and group ids the last modification and last access times if it's a regular or directory, the location of data blocks if it's a special file, device numbers if it's a symbolic link, the value of the symbolic link stat 구조체의필드는 i-node 에서읽어온다 숙대창병모 5
The block map direct block pointers 10 direct block pointers indirect block pointer an indirect block to address 1024 blocks double indirect block pointer an double indirect block to contain 1024 indirect block pointers How many blocks can be addressed? 숙대창병모 6
Block map I-node Direct block pointers... to blocks 0.. 9 Data blocks Indirect pointers To blocks 10.. 1033 Double indirect pointers Locates up to 1000 indirects To blocks 1034.. 2057 숙대창병모 7
File system layout Boot block boot code that is used when UNIX is first activated Super block information about the entire file system the total number of blocks in the file system the number of inodes in the inode free list a bit map of free blocks : see Figure 11.21 the size of block in bytes the number of free blocks the number of used blocks 숙대창병모 8
File system layout i-list all the inodes associated with the files on the disk each block in the inode list can hold about 40 inodes Data blocks for storing file blocks Bad blocks several blocks that cannot be used 숙대창병모 9
File system layout 0 1 2 3 Boot block Super block Inodes 1..40 Inodes 41..80... i-list 200 Data block 201 Data block... Data blocks Data block 숙대창병모 10
3.2 파일상태 숙대창병모 11
파일상태 (file status) 파일상태 파일자체에대한데이터 어떤것들이있을까요? 파일타입 파일크기 소유자 허가권 어디에있나요? i-node 숙대창병모 12
stat() #include <sys/types.h> #include <sys/stat.h> int stat (const char *pathname, struct stat *buf ); int fstat t (int filedes, struct t stat t *buf ); Int lstat (const char *pathname, struct stat *buf ); 역할 파일에대한상태정보를가져와서 stat 구조체에저장한다. 리턴값 buf 성공하면 0, 실패하면 -1 stat 구조체에대한포인터 숙대창병모 13
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 */ }; 숙대창병모 14
stat 구조체 st_atime 마지막으로파일의데이터를읽은시각 st_mtime 마지막으로파일의데이터를수정한시각 st_ctime 파일의내용이아니고이름 / 권한같은상태를변경한시각 st_blksize 가장효율적인 I/O 블럭크 (2 장 8 절 I/O 성능참고, 8192 bytes) st_blocks 파일이차지하고있는공간의크기를 512 byte 블럭의수로 숙대창병모 15
파일타입 보통파일 (Regular file) 데이터를포함하고있는텍스트또는이진화일 디렉토리파일 (Directory file) 파일의이름들과파일정보에대한포인터들을포함 문자특수파일 (Character special file) 시스템에장착된어떤장치를가리키는파일 문자단위로데이터를전송하는장치 블록특수파일 (Block special file) 시스템에장착된어떤장치를가리키는파일 블럭단위로데이터를전송하는장치 숙대창병모 16
파일타입 FIFO 프로세스간통신에사용되는파일 named pipe 라고도불림 소켓 (socket) 네트웍을통한프로세스간통신에사용되는파일 심볼릭링크 (Symbolic link) 다른파일을가리키는포인터역할을하는파일 숙대창병모 17
파일타입검사 파일타입을검사하는매크로함수 #include <sys/stat.h> S_ISREG() : 정규파일 S_ISDIR() : 디렉토리파일 S_ISCHR() : 문자특수파일 S_ISBLK() : 블록특수파일 S_ISFIFO() : pipe 또는 FIFO S_ISLNK() : 심볼릭링크 S_ISSOCK() : 소켓 st_mode 해당종류의파일이면 1, 아니면 0 을리턴 stat 구조체의 st_mode 값을검사함 type special permission 4 3 9 숙대창병모 18
예제 : /* stat.c */ #include <sys/types.h> /* stat.c */ #include <sys/stat.h> int main(int argc, char*argv[]) 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 f(s_ischr(buf.st_mode)) SC (b 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); } 숙대창병모 19
실행결과 % a.out /etc /dev/ttya /bin a.out /etc: directory /dev/ttya:/ symbolic link /bin: symbolic link a.out: regular symbolic link 에대한정보도얻기위해서 stat() 대신 lstat() 를사용 숙대창병모 20
3.3 파일허가권 숙대창병모 21
파일허가권 (File Permissions) i 각파일에대한권한관리 각파일마다허가권이있다. owner/group/others 구분해서관리한다. 파일에대한권한 읽기 r 쓰기 w 실행 x 숙대창병모 22
파일허가권 (File Permissions) 파일허가권 (file access permission) i stat 구조체의 st_mode 의값 st_mode mask Meaning #include <sys/stat.h> S_IRUSR user-read st_mode S_IWUSR user-write type special permission 4 3 9 S_IXUSR S_IRGRP S_IWGRP S_IXGRP S_IROTH S_IWOTH user-execute group-read group-write group-execute other-read other-write S_IXOTH other-execute 숙대창병모 23
허가권 read 권한이있어야 O_RDONLY O_RDWR 을사용하여파일을열수있다 write 권한이있어야 O_WRONLY O_RDWR O_TRUNC 을사용하여파일을열수있다 디렉토리에 write 권한과 execute 권한이있어야 그디렉토리에파일을생성할수있고 그디렉토리의파일을삭제할수있다 삭제할때그파일에대한 read write 권한은없어도됨 숙대창병모 24
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 가사용되고 다음과같은경우만예외 숙대창병모 25
S_ISUID 와 S_ISGID stat 구조체의 st_mode 의비트 S_ISUID : set-user-id st_mode S_ISGID : set-group-id type special permission 4 3 9 S_ISUID 비트가설정된실행파일을실행하는경우 그실행파일이실행된프로세스의 effective user ID 는 사용자의 real user ID 가아니고 st_uid : 그실행파일의소유자 user ID S_ISGID 비트가설정된실행파일을실행하는경우 그실행파일이실행된프로세스의 effective group ID 는 st_gid : 그실행파일의소유자 group ID 숙대창병모 26
예제 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* 숙대창병모 27
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_IRUSR, S_IWUSR, S_IXUSR S_IRGRP, S_IWGRP, S_IXGRP S_IROTH, S_IWOTH, S_IXOTH 숙대창병모 28
예제 #include <sys/types.h> yp #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; 숙대창병모 29
[ 실행결과 ] $ ls -l foo bar -rw------- 1 0 Jul 21 12:04 bar -rw-rw-rw- 1 0 Jul 21 12:04 foo $ a.out $ ls -l foo bar -rw-r--r-- 1 0 Jul 21 12:04 bar -rw-rwsrw- 1 0 Jul 21 12:04 foo 숙대창병모 30
chown() #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() 은심볼릭링크자체를변경한다 super-user 만변환가능 숙대창병모 31
3.4 링크 (link) 숙대창병모 32
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 */ }; 숙대창병모 33
Link count i-node 의 link count stat 구조체의 st_nlink 이 i-node 를가리키는 directory entry 수 파일의삭제 directory block 에서파일을삭제하면 i-node 의 link count 가 1 감소 link count 가 0 에도달하면그파일의 i-node 와 data block 이삭제됨 파일의이동 UNIX 명령어 mv 파일의 data block 이나 i-node 의변화는없이 directory entry 만변경됨 숙대창병모 34
link() #include <unistd.h> int link (const char *existingpath, const char *newpath ); 이미존재하는파일 (existingpath) 에대해서 새로운디렉토리항목 (newpath) 을만든다 리턴값 성공하면 0, 실패하면 -1 hard link 가만들어짐 같은 i-node를가리키는 directory entry가하나생김 그 i-node 의 link count 가하나증가 숙대창병모 35
Link to a File int link(path1, path2) char *path1; char *path2; Directory1 name1 36 i-list main(argc, argv) int argc; char *argv[ ]; { int link(); if (link(argv[1], argv[2]) == -1) {exit(1); } exit(0) } Directory2 name2 36 inode data blocks 숙대창병모 36
unlink() #include <unistd.h> int unlink (const char *pathname); 파일의 link count 를감소시킴 리턴값 성공하면 0, 실패하면 -1 unlink() 는 directory entry 를지우며, 파일의 link count 를 1 감소시킨다 link count 가 0 이되면, 파일을디스크에서제거한다. i-node 와 data block 삭제 숙대창병모 37
예제 : unlink.c #include <sys/types.h> /* unlink.c */ #include <sys/stat.h> #include <fcntl.h> #include "error.h int main() { if (open("tempfile", O_RDWR) < 0) perror( open error ); if (unlink( tempfile ) < 0) perror( unlink error ); printf( file unlinked\n ); sleep(5); printf( done\n ); } exit(0); 숙대창병모 38
rename() #include <unistd.h> int rename (const char *oldname, const char *newname ); 파일이나디렉토리의이름을바꾼다. 리턴값 : 성공하면 0, 실패하면 -1 newname 이이미존재하는경우 oldname이파일을가리키고 newname이파일로서존재할때, 기존을파일을덮어쓴다. oldname 이디렉토리를가리키고 newname 이비어있는디렉토리일때, 기존의디렉토리를덮어쓴다. 숙대창병모 39
Symbolic Link 심볼릭링크 (symbolic link) 는파일에대한간접적인포인터 실제파일에대한경로를저장하고있다 링크의한계점을극복 링크는단일파일시스템에서만허용된다 숙대창병모 40
symlink() #include <unistd.h> int symlink (const char *actualpath, const char *sympath ); 심볼릭링크 sympath 를만든다 심볼릭링크파일의내용은 actualpath 심볼릭링크파일의크기는 actualpath 문자열의길이 리턴값 성공하면 0, 실패하면 -1 actualpath 실제파일 sympath 만들심볼릭링크의이름 숙대창병모 41
utime() #include <sys/types.h> #include <utime.h> int utime (const char *pathname, const struct utimbuf *times ); 파일의최종접근시간과최종변경시간을조정한다. times 가 NULL 이면, 현재시간으로설정된다. 리턴값 성공하면 0, 실패하면 -1 UNIX 명령어 touch 참고 숙대창병모 42
utime() struct utimbuf { time_t actime; /* access time */ time_t modtime; /* modification time */ } 각필드는 1970-1-1 00:00 부터현재까지의경과시간을초로환산한값 숙대창병모 43
예제 :utimec utime.c #include <sys/types.h> yp /* utime.c */ #include <sys/stat.h> #include <fcntl.h> #include <utime.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 */ perror(argv[i]); if (open(argv[i], O_RDWR O_TRUNC) < 0) /* truncate */ perror(argv[i]); timebuf.actime = statbuf.st_atime; timebuf.modtime = statbuf.st_mtime; if (utime(argv[i], &timebuf) < 0) /* reset times */ perror(argv[i]); } return 0; } 숙대창병모 44
3.5 디렉토리 숙대창병모 45
What is a Directory A kind of file used to organize regular, pipe, special files and other directory format imposed by Unix file names are contained only in directory entries permissions r: readable w: writable x: searchable 숙대창병모 46
Directory and File A Directory i-list name 36 inode data blocks 숙대창병모 47
Directory 2 Inode # 1 2 3 4 5 6 Block # 200 dr-xr-xr-x 201 dr-xr-xr-x 202 dr-xr-xr-x bin 3 usr 4 203 -r-xr-xr-x 204,206-r-xr-xr-x Permissions ls 5 cp 7 test.c 6. 2 /usr/test.c 200 201 202 203 204 205 206.. 2 bin 3 usr 4. 3.. 2 ls 5 cp 7. 4.. 2 test.c 6 ls executable test.c 1st block cp executable 숙대창병모 test.c 2nd block 48
Directory 디렉토리파일 일종의파일이므로 open, read, close 함수등을사용할수있다 디렉토리파일사용에편리한새로운함수들도제공된다. 디렉토리파일의내용은구조체 dirent 의배열 d_name : 파일이름, 하위디렉토리이름, ".", ".." d_ino: i-node number #include <dirent.h> struct dirent { ino_t d_ino; /* i-node number */ char d_name[name_max + 1]; /* filename */ } 숙대창병모 49
디렉토리접근 #include <sys/types.h> #include <dirent.h> DIR *opendir (const char *pathname); struct dirent *readdir(dir *dp); opendir() 로디렉토리파일을열고 리턴값 성공하면 DIR 구조체주소, 실패하면 NULL DIR 구조체 열린디렉토리를나타내는구조체 lk like FILE struct 숙대창병모 50
readdir() readdir() 디렉토리내용을읽는다 해당디렉토리에대한읽기권한이있어야한다 한번에 dirent 하나씩읽는다. 디렉토리의 current file position 읽을때마다읽은구조체 dirent 크기만큼증가한다. 직접쓸수없다 그러나쓰기권한이있어도 write 함수로직접쓸수는없다. mkdir rmdir 를사용해야함 숙대창병모 51
rewinddir(), closedir() #include <sys/types.h> #include <dirent.h> void rewinddir (DIR *dp); int closedir (DIR *dp); rewinddir() 디렉토리파일의 current file position 을처음으로옮긴다 closedir() 디렉토리파일을닫는다. 리턴값 : 성공하면 0, 실패하며 -1 숙대창병모 52
mkdir() #include <sys/types.h> #include <sys/stat.h> int mkdir (const char *pathname, mode_t mode ); 새로운디렉토리를만든다. 리턴값 성공하면 0, 실패하면 -1 성공하면 "." 와 ".." 파일은자동적으로만들어진다. "." 은이디렉토리파일의 i-node 를, ".." 은부모디렉토리파일의 i-node 를가르킨다 숙대창병모 53
rmdir() #include <unistd.h> int rmdir (const char *pathname ); 비어있는디렉토리를삭제한다. 디렉토리파일의 link count 를감소시킴 link count 가 0 이되면삭제됨 리턴값 성공하면 0, 실패하면 -1 숙대창병모 54
예제 : listfiles.c #include <sys/types.h> /* listfiles.c */ #include <sys/stat.h> #include <dirent.h> #include <stdio.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'); (p); case S_IFSOCK: return('s'); } return('?'); } 숙대창병모 55
예제 : listfiles.c /* permoffile e -return the file permissions s in an "ls"-like estring. */ char* permoffile(mode_t mode) { int i; char *p; static ti char perms[10]; p = perms; strcpy(perms, "---------"); 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++; } 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); } 숙대창병모 56
예제 : listfiles.c /* outputstatinfo - print out the contents of the stat structure. */ void outputstatinfo(char *pathname, char *filename, struct stat *st) { int n; char slink[bufsiz+1]; 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 (((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)); printf("%.12s ", ctime(&st->st_mtime) + 4); printf("%s", %s, filename); if ((st->st_mode & S_IFMT) == S_IFLNK) { if ((n = readlink(pathname, slink, sizeof(slink))) < 0) printf(" ->???"); else printf(" -> %* %.*s", n, slink); } } 숙대창병모 57
예제 : listfiles.c int main(int argc, char **argv) { DIR *dp; char *dirname, filename[bufsiz+1]; struct stat st; struct dirent *d; while (--argc) { /* for each directory on the command line... */ dirname = *++argv; if ((dp = opendir(dirname)) == NULL) /* Open the directory */ perror(dirname); printf("%s:\n", dirname); while ((d = readdir(dp))!= NULL) { /* For each file in the directory... */ sprintf(filename, "%s/%s", dirname, d->d_name); // the full file name. if (lstat(filename, &st) < 0) /* Find out about it. */ perror(filename); outputstatinfo(filename, d->d_name, &st); // Print out the info putchar('\n'); } putchar('\n'); closedir(dp); } return 숙대0; 창병모 58 }
chdir(), fchdir() #include <unistd.h> int chdir (const char *pathname); int fchdir (int filedes); char *getcwd (char *buf, size_t size ); 현재작업디렉토리를변경한다 현재작업디렉토리경로명을얻는다 반환값 : 성공하면 0, 실패하면 -1 현재작업디렉토리는프로세스의속성 숙대창병모 59