11장 파일.

Slides:



Advertisements
Similar presentations
1.
Advertisements

Linux/UNIX Programming
2. 파일 시스템 파일 디렉터리와 경로명 파일 시스템의 구조 새로운 파일 생성 소유권과 허가 파일 유형과 일반화.
제14장 동적 메모리.
6 레이스 컨디션.
인공지능실험실 석사 2학기 이희재 TCP/IP Socket Programming… 제 11장 프로세스간 통신 인공지능실험실 석사 2학기 이희재
Chapter 3 /etc/passwd real uid(진짜 사용자 식별번호), real gid(진짜 그룹 식별번호)
파일 시스템 및 디렉토리 ©숙대 창병모.
Linux System Programming
제2부 시스템 프로그래밍 파일 및 입출력 2011 가을 숙명여대 창병모 © 숙대 창병모.
08. 디바이스 드라이버의 읽기와 쓰기 김진홍
Linux System Programming
제2장. 파일 입출력 (File I/O) © 숙대 창병모.
Network Lab. Seoung Hyeon, Lee
5장 파일 시스템.
제15장 파일 입출력 문자열을 출력하는 여러가지 방법 (15-2쪽) 문자열만 처리하는 입출력 함수
레이스 컨디션.
쉽게 풀어쓴 C언어 Express 제17장 동적메모리와 연결리스트 C Express Slide 1 (of 13)
UNIT 07 Memory Map 로봇 SW 교육원 조용수.
양방향 파이프의 활용 양방향 통신 파이프는 기본적으로 단방향이므로 양방향 통신을 위해서는 파이프를 2개 생성한다.
12장 파이프.
07. 디바이스 드라이버의 초기화와 종료 김진홍
CHAPTER 02 OpenCV 개요 PART 01 영상 처리 개요 및 OpenCV 소개.
레이스 컨디션 컴퓨터공학과 4학년 이교욱.
Dynamic Memory and Linked List
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
9장 파일 입출력.
링크 파일 생성[1] 링크 하드링크 생성 : link(2) 이미 있는 파일이나 디렉토리에 접근할 수 있는 새로운 이름
3 파일과 디렉토리.
Linux/UNIX Programming APUE (Files & Directories)
Linux/UNIX Programming APUE (Files & Directories)
4장 파일의 관리 서론 예제 프로그램 함수 - umask - access
컴퓨터 프로그래밍 기초 #02 : printf(), scanf()
시스템 호출 read , write의 효율성 lseek test example – test1.c 실습 – 연습문제 2.8
Linux/UNIX Programming
Homework 6… 12월 2일(금) 11:59pm까지 자신의 이름과 학번을 출력해 주는 유닉스/리눅스 네트워크 소켓 서버 프로그램 과 클라이언트 프로그램 을 작성해 보세요 참고 (실습1) Hello 프로그램 helloserver.c helloclient.c 컴파일.
파일 기술자 복사 파일 기술자 복사 : dup(2) 파일 기술자 복사 : dup2(3)
8 메모리 매핑.
파일 기술자 파일 기술자 현재 열려있는 파일을 구분하는 정수값 저수준 파일 입출력에서 열린 파일을 참조하는데 사용
(ioctl, mmap, fsync&flush)
4장 파일.
6장 파일 및 레코드 잠금.
Linux/UNIX Programming
메시지 큐[5] – test1.c 메시지 제어: msgctl(2) #include <sys/msg.h>
파일 접근권한 제어 stat 구조체의 st_mode 항목에 파일의 종류와 접근권한 정보저장 st_mode 값의 구조.
TCP/IP Socket Programming…
FILE I/O 번째주 Dept. of Computer Science & Engineering
10장 C 표준 파일 입출력 子曰 學而時習(실습?)之 不亦悅乎.
사용자 함수 사용하기 함수 함수 정의 프로그램에서 특정한 기능을 수행하도록 만든 하나의 단위 작업
Linux Programming Spring 2008
13장 프로세스 사이의 통신.
Memory & Data Management.
Linux/UNIX Programming
24장. 파일 입출력.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express Slide 1 (of 22)
네트워크 프로그래밍의 이해 School of Electronics and Information.
3 파일과 디렉토리.
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
Linux/UNIX Programming
Linux/UNIX Programming
Homework 7… 마지막 수업시간까지 (실습) 매개변수로 입력 받아 처리할 수 있도록 수정해 보세요
시스템 인터페이스 Lab#5 쉡 실습.
시스템 인터페이스 Lab1 X-window 및 명령어 사용.
구조체(struct)와 공용체(union)
Chapter 12 파일 입출력.
제 4 장 Record.
06. 디바이스의 등록과 해제 김진홍
3장 파일 다루기 한빛미디어(주).
시스템 해킹과 보안 permission과 SetUID.
2019 2학기 9장 배열과 포인터 1. 주소, 주소연산자(&) 2. 포인터, 역참조연산자(*) 3. 배열과 포인터.
Presentation transcript:

11장 파일

11.1 시스템 호출

유닉스/리눅스 커널(kernel) 하드웨어를 운영 관리하여 다음과 같은 서비스를 제공 프로세스 관리(Process management) 파일 관리(File management) 메모리 관리(Memory management) 통신 관리(Communication management) 주변장치 관리(Device management)

시스템 호출(system call) 시스템 호출은 유닉스/리눅스 커널에 서비스를 요청하기 위한 프로 그래밍 인터페이스 응용 프로그램은 시스템 호출을 통해서 유닉스/리눅스 커널에 서비 스를 요청한다 /usr/include/asm/unistd_32.h 참조

11.2 파일

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

파일 열기: open() 파일을 사용하기 위해서는 먼저 open() 시스템 호출을 이용하여 파일을 열어야 한다 파일 디스크립터는 열린 파일을 나타내는 번호 oflag, mode : 교재 331~332 쪽, /usr/include/bits/fcntl.h 참조 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open (const char *path, int oflag, [ mode_t mode ]); 파일 열기에 성공하면 파일 디스크립터를 리턴, 실패하면 -1을 리턴

파일 열기: 예 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)

fopen.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); } fd 번호를 출력해보세요! 매개변수 없을 경우도 잘 처리하도록 debug 해보세요!

파일 생성: creat() creat() 시스템 호출 path가 나타내는 파일을 생성하고 쓰기 전용으로 연다 생성된 파일의 사용권한은 mode로 정한다 기존 파일이 있는 경우에는 그 내용을 삭제하고 연다 다음 시스템 호출과 동일 open(path, WRONLY | O_CREAT | O_TRUNC, mode); #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int creat (const char *path, mode_t mode ); 파일 생성에 성공하면 생성된 파일의 파일 디스크립터, 실패하면 -1을 리턴

파일 닫기: close() close() 시스템 호출은 fd가 나타내는 파일을 닫는다 #include <unistd.h> int close( int fd ); fd가 나타내는 파일을 닫는다. 성공하면 0, 실패하면 -1을 리턴한다.

데이터 읽기: read() read() 시스템 호출 fd가 나타내는 파일에서 nbytes 만큼의 데이터를 읽고 읽은 데이터는 buf에 저장한다 #include <unistd.h> ssize_t read ( int fd, void *buf, size_t nbytes ); 파일 읽기에 성공하면 읽은 바이트 수, 파일 끝을 만나면 0, 실패하면 -1을 리턴

fsize.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); } $ gcc –o fsize fsize.c $ fsize xx 매개변수 없을 경우도 잘 처리하도록 debug 해보세요!

데이터 쓰기: write() write() 시스템 호출 buf에 있는 nbytes 만큼의 데이터를 fd가 나타내는 파일에 쓴다 #include <unistd.h> ssize_t write (int fd, void *buf, size_t nbytes); 파일에 쓰기를 성공하면 실제 쓰여진 데이터의 바이트 수를 리턴하고, 실패하면 -1을 리턴

fcp.c BUFSIZ 값 출력해보기 $ grep BUFSIZ /usr/include/* #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); BUFSIZ 값 출력해보기 $ grep BUFSIZ /usr/include/*  O_APPEND

(보충) $ man $ man read $ whatis read $ man –f read (Unix) $ man –l read read (1p) - read a line from standard input read (2) - read from a file descriptor read (3p) - read from a file read [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 1절 명령어 2절 시스템 호출 3절 라이브러리 함수 4절 특수화일 5절 파일 형식 6절 게임 7절 기타 정보 8절 유지보수 명령어 9절 커널 루틴 1 Executable programs or shell commands 2 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/passwd 6 Games 7 Miscellaneous (including macro packages and conven-tions 8 System administration commands (usually only for root) 9 Kernel routines [Non standard]

(보충) set-user-id set-group-id set-sticky-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 생성시 허가권 제한 - rws r-x --x - 100 111 101 001 - rwx r-s --x - 010 111 101 001 - rwx r-x --t - 001 111 101 001

(보충) IA-32(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

(보충) 비트단위 정수 출력 bitwise.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(' '); $ gcc –o bitwise bitwise.c $ bitwise -99 short 형을 int 형으로 수정하세요! 매개변수 없을 경우도 잘 처리하도록 debug 하세요!

11.3 현재 파일 위치

파일 위치 포인터(file position pointer) 파일 위치 포인터는 파일 내에 읽거나 쓸 위치인 현재 파일 위치 (current file position)를 가리킨다.

파일 위치 포인터 이동: lseek() lseek() 시스템 호출 임의의 위치로 파일 위치 포인터를 이동시킬 수 있다. #include <unistd.h> off_t lseek (int fd, off_t offset, int whence ); 이동에 성공하면 현재 위치를 리턴하고 실패하면 -1을 리턴한다.

파일 위치 포인터이동: 예 파일 위치 이동 레코드 단위로 이동 파일끝 이후로 이동 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); 파일끝에서 한 레코드 다음 위치로

레코드 저장 예 $ vi student.h write(fd, &record1, sizeof(record)); #define MAX 20 struct student { int id; char name[MAX]; int score; }; write(fd, &record1, sizeof(record)); write(fd, &record2, sizeof(record)); lseek(fd, sizeof(record), SEEK_END); write(fd, &record3, sizeof(record)); 레코드 #1 레코드 #2 레코드 #3

dbcreate.c $ gcc –o dbcreate.c dbcreate.c $ dbcreate stdb #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); } 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

dbquery.c $ gcc –o dbquery.c dbquery.c $ dbcreate stdb #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); 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

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

dbupdate.c $ gcc –o dbupdate.c dbupdate.c $ dbupdate stdb #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); 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

11.4 파일 상태 정보

파일 상태(file status) 파일 상태 예 $ ls -sl hello 파일에 대한 모든 정보 블록수, 파일 타입, 접근 권한, 링크수, 파일 소유자의 사용자 ID, 그룹 ID, 파일 크기, 최종 수정 시간 등 예 $ ls -sl hello 2 -rw-r--r-- 1 mysung other 617 11월 26일 15:59 hello.c 블록수 사용권한 링크수 사용자ID 그룹ID 파일크기 최종 수정 시간 파일이름  파일 타입 Linux: $ getconf PAGESIZE 또는 PAGE_SIZE (4096) Solaris: $ pagesize –a (4096, 2097152)

상태 정보: stat() 파일 하나당 하나의 i-노드가 있으며 i-노드 내에 파일에 대한 모든 상태 정보가 저장되어 있다 Q: stat()과 lstat()의 차이점은?  $ man –s 2 stat #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을 리턴한다.

stat 구조체 /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; /* 최종 상태 변경 시간 */ };

파일 타입과 매크로 함수 /usr/include/sys/stat.h 127행 참조 /usr/include/bits/stat.h 142행 참조 파일 타입 설명 파일 타입을 검사하기 위한 매크로 함수 일반 파일 데이터를 갖고 있는 텍스트 파일 또는 이진 파일 S_ISREG() 디렉터리 파일 파일의 이름들과 파일 정보에 대한 포인터를 포함하는 파일 S_ISDIR() 문자 장치 파일 문자 단위로 데이터를 전송하는 장치를 나타내는 파일 S_ISCHR() 블록 장치 파일 블록 단위로 데이터를 전송하는 장치를 나타내는 파일 S_ISBLK() FIFO 파일 프로세스 간 통신에 사용되는 파일로 이름 있는 파이프 S_ISFIFO() 소켓 네트워크를 통한 프로세스 간 통신에 사용되는 파일 S_ISSOCK() 심볼릭 링크 다른 파일을 가리키는 포인터 역할을 하는 파일 S_ISLNK()

ftype.c $ gcc –o ftype ftype.c $ ln -s xx yy $ ftype xx yy $ ftype * #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); ftype.c $ gcc –o ftype ftype.c $ ln -s xx yy $ ftype xx yy $ ftype * $ ftype /dev/* | more st_ino와 st_size 출력해 보세요! Q: stat()과 lstat()의 차이점은?

파일 상태 정보 변경 chmod() 시스템 호출 파일의 상태 정보를 변경 #include <sys/types.h> #include <sys/stat.h> int chmod(const char *path, mode_t mode); path가 나타내는 파일의 사용권한을 mode로 변경한다

fchmod.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); $ gcc –o fchmod fchmod.c $ fchmod 666 xx $ ls –asl xx $ man atoi int atoi(const char *nptr); = strtol(nptr, (char **)NULL, 10); # 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행

11.5 디렉터리

디렉터리 구현 디렉터리 내에는 무엇이 저장되어 있을까? 디렉터리 엔트리 #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! */ }; DIR

디렉터리 리스트 opendir() readdir() 디렉터리 열기 함수 DIR 포인터(열린 디렉터리를 가리키는 포인터) 리턴 디렉터리 읽기 함수 #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행

list1.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); } $ gcc –o list1 list1.c $ list1 $ list1 /usr

파일 이름/크기 프린트 디렉터리 내에 있는 파일 이름과 그 파일의 크기(블록의 수)를 프린트하도 록 확장 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'); }

디렉터리 리스트: 예 list2.c 프로그램 구성 ls –l 명령어처럼 파일의 모든 상태 정보를 프린트 main() 메인 프로그램 printStat() 파일 상태 정보 프린트 type() 파일 타입 리턴 perm() 파일 접근권한 리턴 Q: 한 블록의 크기는? Linux: $ getconf PAGESIZE 또는 PAGE_SIZE (4096) Solaris: $ pagesize –a (4096, 2097152)

list2.c $ gcc –o list2 list2.c $ list2 $ list2 | sort +9 -10 $ ls -asl #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); list2.c $ gcc –o list2 list2.c $ list2 $ list2 | sort +9 -10 $ ls -asl $ list2 /bin (/bin/su 파일로 확인)

list2.c (계속) 교재 코드 Debug  채워 넣으세요 st_ino 출력해 보세요 Q: 파일시스템 I/O 최적 블록 크기는? /* 파일 상태 정보를 출력 */ 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'); 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. */

디렉터리 만들기 mkdir() 시스템 호출 path가 나타내는 새로운 디렉터리를 만든다 "." 와 ".." 파일은 자동적으로 만들어진다 #include <sys/types.h> #include <sys/stat.h> int mkdir (const char *path, mode_t mode ); 새로운 디렉터리 만들기에 성공하면 0, 실패하면 -1을 리턴한다

디렉터리 삭제 rmdir() 시스템 호출 path가 나타내는 디렉터리가 비어 있으면 삭제한다 #include <unistd.h> int rmdir (const char *path); 디렉터리가 비어 있으면 삭제한다. 성공하면 0, 실패하면 -1을 리턴

링크 링크는 기존 파일에 대한 또 다른 이름으로 하드 링크와 심볼릭(소프트) 링크가 있다 #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을 리턴한다

링크의 구현 link() 시스템 호출 기존 파일 existing에 대한 새로운 이름 new 즉 링크를 만든다

하드 링크 vs 심볼릭 링크 하드 링크(hard link) 심볼릭 링크(symbolic link) 지금까지 살펴본 링크 같은 파일 시스템 내에서만 사용될 수 있다 심볼릭 링크(symbolic link) 소프트 링크(soft link) 실제 파일의 경로명 저장하고 있는 링크 파일에 대한 간접적인 포인터 역할을 한다 다른 파일 시스템에 있는 파일도 링크할 수 있다

link.c #include <unistd.h> #include <stdlib.h> int main(int argc, char *argv[ ]) { if (link(argv[1], argv[2]) == -1) { exit(1); } exit(0);

unlink.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);

slink.c #include <unistd.h> #include <stdlib.h> int main(int argc, char *argv[ ]) { if (symlink(argv[1], argv[2]) == -1) { exit(1); } exit(0);

핵심 개념 시스템 호출은 유닉스 커널에 서비스를 요청하기 위한 프로그래밍 인 터페이스로 응용 프로그램은 시스템 호출을 통해서 유닉스 커널에 서 비스를 요청한다 파일 디스크립터는 열린 파일을 나타낸다 파일 위치 포인터는 파일 내에 읽거나 쓸 위치인 현재 파일 위치를 가 리킨다 파일 하나당 하나의 i-노드가 있으며 i-노드 내에 파일에 대한 모든 상태 정보가 저장되어 있다 디렉터리는 일련의 디렉터리 엔트리들을 포함하고 각 디렉터리 엔트 리는 파일 이름과 그 파일의 i-노드 번호로 구성된다 링크는 기존 파일에 대한 또 다른 이름으로 하드 링크와 심볼릭(소프트 ) 링크가 있다