컴퓨터특강 () [Ch. 4] 2005 년봄학기 문양세컴퓨터과학과강원대학교자연과학대학
강의목표및내용 강의목표 파일의상태및구조를이해한다. 파일시스템구현을이해한다. 디렉토리구조및구현을이해한다. 강의내용 파일상태 파일접근허가권 파일시스템구현 링크 (link) 디렉토리 Page 2
stat() 파일상태확인 #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 구조체에얻어온다. buf: stat 구조체에대한포인터 ( 정보를가져올장소 ) lstat() 은 Symbolic Link가가리키는파일이아닌 Symbolic Link 자체에대한정보를얻는다. 리턴값 : 성공하면 0, 실패하면 -1 Page 3
stat 구조체 (1/2) <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 */ }; Page 4
stat 구조체 (2/2) st_atime: 마지막으로파일의데이터를읽은시각 st_mtime: 마지막으로파일의데이터를수정한시각 st_ctime: 파일의내용이아니고이름 / 권한같은상태를변경한시각 st_blksize: 가장효율적인 I/O 블럭크기 ( 예 : 8192 bytes) st_blocks: 파일이차지하고있는공간의크기 (512 byte 의블록수 ) Page 5
파일타입 (1/3) 보통파일 (Regular File) 데이터를포함하고있는텍스트또는이진파일 디렉토리파일 (Directory File) 파일의이름들과파일정보에대한포인터들을포함 문자특수파일 (Character Special File) 시스템에장착된어떠장치를가리키는파일 문자단위로데이터를전송하는장치 (c---------) 블록특수파일 (Block Special File) 시스템에장착된어떤장치를가리키는파일 블럭단위로데이터를전송하는장치 (b---------) Page 6
파일타입 (2/3) 특수파일예제 Page 7
파일타입 (3/3) FIFO 프로세스간통신에사용되는파일 (IPC Programming에서사용됨 ) Named Pipe라고도부름 소켓 (socket) 네트워크를통한프로세스간통신에사용되는파일 Network Programming에서사용하는보편적인방법 심볼릭링크 (Symbolic link) 다른파일을가리키는포인터역할을하는파일 (Windows 의 바로가기 에해당 ) Page 8
파일타입검사 (1/2) 파일타입을검사하는매크로함수 stat.h 파일 (/usr/include/sys/stat.h) 에정의되어있음 S_ISREG() S_ISDIR() S_ISCHR() S_ISBLK() : 정규파일 : 디렉토리파일 : 문자특수파일 : 블록특수파일 st_mode type special permission 4 bits 3 bits 9 bits S_ISFIFO() : pipe 또는 FIFO S_ISLNK() : 심볼릭링크 S_ISSOCK() : 소켓 해당종류의파일이면 1, 아니면 0 을리턴 stat 구조체의 st_mode 값을검사함 Page 9
파일타입검사 (2/2) 파일타입상수 stat.h 파일 (/usr/include/sys/stat.h) 에정의되어있음 S_IFREG S_IFDIR S_IFCHR S_IFBLK : 정규파일 : 디렉토리파일 : 문자특수파일 : 블록특수파일 S_IFFIFO : pipe 또는 FIFO S_IFLNK : 심볼릭링크 S_IFSOCK : 소켓 S_ISxxx() 매크로함수는 S_IFxxx 상수값의설정여부를판단 Page 10
예제 : stat.c (1/2) #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); } Page 11
예제 : stat.c (2/2) 실행결과 $ a.out /etc /dev/ttya /bin a.out /etc: directory /dev/ttya: symbolic link /bin: symbolic link a.out: regular Symbolic Link 에대한정보도얻기위해서 stat() 대신 lstat() 을사용 Page 12
파일허가권 (File Permissions) File access permission bits (stat 구조체의 st_mode 값 ) st_mode type special permission 4 bits 3 bits 9 bits st_mode mask Meaning Octal Code S_IRUSR user-read 0400 S_IWUSR user-write 0200 S_IXUSR S_IRGRP S_IWGRP S_IXGRP S_IROTH S_IWOTH S_IXOTH user-execute group-read group-write group-execute other-read other-write other-execute 0100 0040 0020 0010 0004 0002 0001 Page 13
관련명령어 UNIX 명령어 chmod File Access Permission 설정 stat 구조체의 st_mode 값을변경 UNIX 명령어 chown File 소유 User ID 설정 stat 구조체의 st_uid 값을변경 UNIX 명령어 chgrp File 소유 Group ID 설정 stat 구조체의 st_gid Page 14
허가권 (Permissions) (1/2) Read 권한이있어야 O_RDONLY, O_RDWR 를사용하여파일을열수있다. Write 권한이있어야 O_WRONLY, O_RDWR, O_TRUNC 를사용하여파일을열수있다. 디렉토리에 write 권한과 execute 권한이있어야 해당디렉토리에파일을생성할수있고, 그디렉토리의파일을삭제할수있다 Page 15
허가권 (Permissions) (2/2) 파일이포함된모든상위디렉토리에대해 execute 권한이있어야그파일을열수있다. 디렉토리에대한 read 권한이있어야디렉토리안에들어있는파일이름목록을읽을수있다. 디렉토리에대한 write 권한이있어야디렉토리에파일을생성삭제할수있다. 디렉토리에대한 execute 권한이있어야그디렉토리나그하위디렉토리에있는파일을열수있다. Page 16
Effective User ID Real User ID 와 Real Group ID 실제사용자 ID와그사용자가속한그룹 ID 로그인한사용자 ID 일반적으로, Shell 상에서작업을수행할때의 User 및 Group ID로이해할수있음 Effective User ID 와 Effective Group ID 프로세스의속성 대부분의경우 Real User ID 와 Real Group ID 가사용되나, 다음에설명하는 S_ISUID와 S_ISGID 비트가 Set된경우에는다르게동작함 일반적으로, 프로세스가수행될때의 User ID 및 Group ID로이해할수있음 Page 17
S_ISUID 와 S_ISGID (1/2) stat 구조체의 st_mode 의비트로표현됨 S_ISUID : set-user-id S_ISGID : set-group-id st_mode type special permission 4 bits 3 bits 9 bits st_mode 의 S_ISUID 비트가설정된실행파일을실행한경우 그실행파일이실행된프로세스의 Effective User ID는 Real User ID가아니고, 그실행파일소유자의 User ID가된다. st_mode 의 S_ISGID 비트가설정된실행파일을실행한경우 그실행파일이실행된프로세스의 Effective Group ID는 Real Group ID가아니고, 그실행파일소유자의 group ID가된다. Page 18
S_ISUID 와 S_ISGID (2/2) 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* Page 19
access() #include <unistd.h> int access (const char *pathname, int mode ); Real User ID 와 Real Group ID 로파일의허가권검사 리턴값 : 성공하면 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 Page 20
예제 : access() #include <sys/types.h> // access.c #include <fcntl.h> #include <unistd.h> int main(int argc, char *argv[]) { if (argc!= 2) { printf("usage: a.out <pathname>\n"); exit(-1); } if (access(argv[1], R_OK) < 0) perror("r_ok"); else printf("read access OK\n"); if (open(argv[1], O_RDONLY) < 0) perror("o_rdonly"); else printf("open for reading OK\n"); } return 0; Page 21
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 Page 22
예제 : chmod() (1/2) #include <sys/types.h> // nchmod.c #include <sys/stat.h> int main() { struct stat statbuf; /* turn on both set-group-id and group-execute */ if (stat("foo", &statbuf) < 0) perror("stat(foo)"); if (chmod("foo", (statbuf.st_mode S_IXGRP S_ISGID)) < 0) perror("chmod(foo)"); /* set absolute mode to "rw-r--r--" */ if (chmod("bar", S_IRUSR S_IWUSR S_IRGRP S_IROTH) < 0) perror("chmod(bar)"); } return 0; Page 23
예제 : chmod() (2/2) 실행결과 Page 24
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() 은심볼릭링크자체를변경한다. UNIX 종류및버전에따라차이가있을수있다. BSD 기반시스템에서는 super-user 만변환가능 System V 계열시스템은일반사용자도변경가능 Page 25
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 Page 26
강의목표및내용 강의목표 파일의상태및구조를이해한다. 파일시스템구현을이해한다. 디렉토리구조및구현을이해한다. 강의내용 파일상태 파일접근허가권 파일시스템구현 링크 (link) 디렉토리 Page 27
Block I/O I/O is always done in terms of blocks. Sequence of a read() system call read() system call trap n bytes I/O request the device driver (software in kernel) the disk controller (hardware) one block at a time interrupt Page 28
Inode (Index Node) 한파일은하나의 i-node를갖는다. 파일에대한정보를가지고있다. 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 에서읽어온다. Page 29
The Block Map (1/2) 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? You may meet this question in the final exam. Page 30
The Block Map (2/2) Inode Disk blocks Direct block pointers... to blocks 0.. 9 Indirect pointers Double indirect pointers To blocks 10.. 1033 (1024 blocks) Locates up to 1000 indirects To blocks 1034.. 2057 Page 31
File System Layout (1/3) 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 the size of block in bytes the number of free blocks the number of used blocks Page 32
File System Layout (2/3) i-list ( 다음페이지참조 ) all the inodes associated with the files on the disk each block in the inode list can hold about 40 inodes User Blocks for storing file blocks Bad Blocks Several block that cannot be used Page 33
File System Layout (3/3) 0 1 2 3 200 201 Boot block Super block Inodes 1..40 Inodes 41..80... User block User block... User block i-list User blocks Page 34
강의목표및내용 강의목표 파일의상태및구조를이해한다. 파일시스템구현을이해한다. 디렉토리구조및구현을이해한다. 강의내용 파일상태 파일접근허가권 파일시스템구현 링크 (link) 디렉토리 Page 35
unlink() #include <unistd.h> int unlink (const char *pathname); 파일을삭제하는역할을수행함 ( 엄밀히말해서, 파일의 link count를감소시킴 ) stat 구조체의 st_mode 변경 리턴값 : 성공하면 0, 실패하면 -1 파일이삭제될경우, inode와 data block이삭제 (free) 된다. Page 36
예제 : unlink() (1/2) #include <sys/types.h> // unlink.c #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main() { int fd, len; char buf[20]; fd = open("tempfile", O_RDWR O_CREAT O_TRUNC, 0666); if (fd == -1) perror("open1"); close(fd); system("ls -l"); unlink("tempfile"); system("ls -l"); } return 0; Page 37
예제 : unlink() (2/2) 실행결과 Page 38
symlink() - Symbolic Link Symbolic Link 는파일에대한간접적인포인터임 실제파일에대한 경로 를저장하고있는파일임 #include <unistd.h> int symlink (const char *actualpath, const char *sympath ); Symbolic Link 를만든다. Symbolic Link File의내용은actualpath에해당함 Symbolic Link File의크기는actualpath 문자열의길이 ( 즉, 저장되는내용이문자열 ) 리턴값 : 성공하면 0, 실패하면 -1 파라미터설명 actualpath: 실제파일 sympath: 만들 Symbolic Link의이름 Page 39
파일관련시간 stat 구조체의 st_atime 파일의데이터가마지막으로읽혔던 (read 되었던 ) 시간 즉, 마지막으로 read() 가호출된시간 stat 구조체의 st_mtime 파일의데이터가마지막으로변경 (write) 된시간 즉, 마지막으로 write() 가호출된시간 stat 구조체의 st_ctime 파일의 stat 구조체의내용이마지막으로변경된시간 chmod(), chown() 등이호출된시간 Page 40
utime() #include <sys/types.h> #include <utime.h> int utime (const char *pathname, const struct utimbuf *times ); 파일의최종접근시간과최종변경시간을조정한다. times가 NULL 이면, 현재시간으로설정된다. 리턴값 : 성공하면 0, 실패하면 -1 UNIX 명령어 touch 참고 struct utimbuf { time_t actime; /* access time */ time_t modtime; /* modification time */ } 각필드는 1970-1-1 00:00 부터현재까지의경과시간을초로환산한값 Page 41
디렉토리 (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 */ } Page 42
디렉토리접근 (opendir(), readdir()) #include <sys/types.h> #include <dirent.h> DIR *opendir (const char *pathname); struct dirent *readdir(dir *dp); opendir() 로디렉토리파일을열고, readdir() 로디렉토리파일의내용을읽는다. 읽을때마다디렉토리파일의 current file offset은읽은구조체 dirent의크기만큼증가한다. 디렉토리의항목읽기위해서는해당디렉토리에대한읽기권한이있어야한다. 그러나, 쓰기권한이있어도 write 함수로직접쓸수는없으며, mkdir(), rmdir() 함수를사용해야한다. 리턴값 : 성공하면구조체주소, 실패하면 NULL Page 43
rewinddir(), closedir() #include <sys/types.h> #include <dirent.h> void rewinddir (DIR *dp); int closedir (DIR *dp); rewinddir() 디렉토리파일의 current file offset 을처음으로옮긴다. ( 첫번째엔트리로옮긴다.) closedir() 디렉토리파일을닫는다. 리턴값 : 성공하면 0, 실패하면 -1 Page 44
mkdir() #include <sys/types.h> #include <sys/stat.h> int mkdir (const char *pathname, mode_t mode ); 새로운디렉토리를만든다. 리턴값 : 성공하면 0, 실패하면 -1 성공하면,. 와.. 파일은자동적으로만들어진다.. 은현재디렉토리파일의 i-node를,.. 은부모디렉토리파일의 i-node를각각가리킨다. Page 45
rmdir() #include <unistd.h> int rmdir (const char *pathname ); 비어있는디렉토리를삭제한다. 리턴값 : 성공하면 0, 실패하면 -1 Page 46
예제 : listfiles.c (1/5) #include <sys/types.h> // listfiles.c #include <sys/mkdev.h> #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'); case S_IFSOCK: return('s'); } return('?'); } Page 47
예제 : listfiles.c (2/5) /* 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, "---------"); 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'; } return(perms); Page 48
예제 : listfiles.c (3/5) /* 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", filename); if ((st->st_mode & S_IFMT) == S_IFLNK) { if ((n = readlink(pathname, slink, sizeof(slink))) < 0) printf(" ->???"); else printf(" -> %.*s", n, slink); } Page 49
예제 : listfiles.c (4/5) 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; 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... */ /* Create the full file name. */ sprintf(filename, "%s/%s", dirname, d->d_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; } Page 50
예제 : listfiles.c (5/5) 실행결과 Page 51
chdir(), fchdir() #include <unistd.h> int chdir (const char *pathname); int fchdir (int filedes); 현재작업디렉토리를변경한다. ($ cd) 반환값 : 성공하면 0, 실패하면 -1 현재작업디렉토리는프로세스의속성 ( 프로세스의 working directory가변하는것임 ) Page 52
getcwd() #include <unistd.h> char *getcwd (char *buf, size_t size ); 현재작업디렉토리의경로명을얻는다. ($ pwd) 반환값 : 성공하면 buf 의주소, 실패하면 NULL Page 53
예제 : chdir(), getcwd() (1/2) #include <unistd.h> // ncd.c #include <stdio.h> #define PATH_MAX 1024 int main(int argc, char **argv) { char path[path_max+1]; if (argc == 1) exit(-1); if (argc == 2) { if(getcwd(path, PATH_MAX) == NULL) perror("error getcwd"); else printf("current working directory changed to %s \n", path); } if(chdir(argv[1]) < 0) perror("error chdir"); else { if(getcwd(path, PATH_MAX) == NULL) perror("error getcwd"); else printf("current working directory changed to %s \n", path); } } else perror("too many arguments"); Page 54
예제 : chdir(), getcwd() (2/2) 실행결과 Page 55
sync(), fsync() #include <unistd.h> void sync(); int fsync(int filedes); 버퍼에있는내용을디스크에쓰도록한다. sync() 는시스템데몬프로세스에의해서 30초마다호출된다. fsync() 는지정된파일에대해서만 I/O 작업을수행하도록한다. 참고 ) O_SYNC 플래그 ( 모든 write() 를 sync mode 로처리함 ) Page 56
Homework #9 파일의 Permission 정보를다음과같이출력하는 myfinfo 를작성하여메일로제출한다. (Wide Card 문자는처리할필요없음 ) $ myfinfo somefile Owner Read = YES ( 혹은 NO) Owner Write = YES ( 혹은 NO) Owner Execute = YES ( 혹은 NO) Group Read = YES ( 혹은 NO) Group Write = YES ( 혹은 NO) Group Execute = YES ( 혹은 NO) Other Read = YES ( 혹은 NO) Other Write = YES ( 혹은 NO) Other Execute = YES ( 혹은 NO) Due Date: 6/1( 수 ) Page 57