Linux System Programming

Slides:



Advertisements
Similar presentations
TCP 서버/클라이언트 동작 원리 - (1) TCP 서버/클라이언트 예 웹 서버 웹 클라이언트 웹 클라이언트
Advertisements

Linux System Programming
Understanding of Socket and File I/O
6 레이스 컨디션.
13장 소켓.
01 화일의 기본 개념 02 화일 저장장치 03 화일 입출력 제어 04 순차화일 05 화일의 정렬 06 화일의 합병
Chapter 10– 표준 함수(1) Outline 10.1 스트림과 파일 10.2 입출력 표준 함수
제 8 장  파서 생성기 YACC 사용하기.
제2부 시스템 프로그래밍 파일 및 입출력 2011 가을 숙명여대 창병모 © 숙대 창병모.
Department of Computer Engineering
인공지능실험실 석사 2학기 김승겸 TCP/IP Socket Programming… 제 10장 멀티태스킹 기반의 서버구현 인공지능실험실 석사 2학기 김승겸
Signal & Inter-Process Communication
디바이스 드라이버 기초 디바이스 드라이버의 개요 파일 연산 디바이스 드라이버 등록 디바이스 드라이버 구성
디바이스 드라이버 개요 가상 디바이스드라이버 실습
Linux System Programming
쉽게 풀어쓴 C언어 Express 제18장 입출력과 라이브러리 함수 C Express.
쉽게 풀어쓴 C언어 Express 제17장 동적 메모리와 연결 리스트 C Express.
제2장. 파일 입출력 (File I/O) © 숙대 창병모.
Network Lab. Seoung Hyeon, Lee
호스트이름과 네트워크이름 찾기 (Hostname and Network Name Lookups)
Linux System Programming
6장 비연결형 지향 프로토콜 Database Lab 강 우 석.
14장 소켓.
제 12장 I/O멀티플렉싱(Multiplexing)
FND (Flexible Numeric Display)
쉽게 풀어쓴 C언어 Express 제17장 동적 메모리와 연결 리스트 C Express.
쉽게 풀어쓴 C언어 Express 제17장 동적메모리와 연결리스트 C Express.
동적메모리와 연결리스트 컴퓨터시뮬레이션학과 2016년 봄학기 담당교수 : 이형원 E304호,
Department of Computer Engineering
Linux System Programming
12장 파이프.
fork로 생성한 자식 프로세스에서 exec 함수군을 호출
Linux System Programming
멀티쓰레드 기반의 서버구현 School of Electronics and Information.
레이스 컨디션 컴퓨터공학과 4학년 이교욱.
9장 파일 입출력.
링크 파일 생성[1] 링크 하드링크 생성 : link(2) 이미 있는 파일이나 디렉토리에 접근할 수 있는 새로운 이름
Term Project Team Member
시스템 호출 read , write의 효율성 lseek test example – test1.c 실습 – 연습문제 2.8
파일 기술자 복사 파일 기술자 복사 : dup(2) 파일 기술자 복사 : dup2(3)
8 메모리 매핑.
Advanced Socket Programming
(ioctl, mmap, fsync&flush)
4장 파일.
6장 파일 및 레코드 잠금.
11장 파일.
Department of Computer Engineering
FILE I/O 번째주 Dept. of Computer Science & Engineering
10장 C 표준 파일 입출력 子曰 學而時習(실습?)之 不亦悅乎.
제 11 장 전처리기.
문자 디바이스 드라이버 임베디드 시스템.
12. 시스템 프로그래밍 (System Programming)
Signal & Inter-Process Communication
Linux Programming Spring 2008
13장 프로세스 사이의 통신.
Memory & Data Management.
네트워크 프로그래밍의 이해 School of Electronics and Information.
리눅스 디바이스 드라이버 (Linux Device Driver)
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
Stepper Motor 디바이스 드라이버
조 병 규 Software Quality Lab. 한국교통대학교
6장 반복제어문 for 문 while 문 do while 문 기타 제어문.
8. 리눅스의 내부 군자삼락 [君子三樂] 청출어람이청어람 [ 靑出於藍而靑於藍 ] Why Linux ?
뇌를 자극하는 C 프로그래밍.
쉽게 풀어쓴 C언어 Express 제6장 조건문 C Express.
실습과제 1번 생성된 파일 basic.txt를 프로젝트 폴더에서 메모장으로 열고 내용을 확인
argc, argv 의 사용방법 #include <stdio.h>
Signal & Inter-Process Communication
C 13장. 입출력 라이브러리 #include <stdio.h> int main(void) { int num;
3장 파일 다루기 한빛미디어(주).
Presentation transcript:

Linux System Programming Lecture #2 – 입출력 시스템 호출

파일 시스템의 내부 구조 (1) 파일 시스템 배치: 1 2 n+2 부트스트랩 블록 슈퍼 블록 inode 블록들(n 개) 데이터 블록들 inode 블록들(n 개) 슈퍼 블록 부트스트랩 블록 LINUX 로드를 이한 하드웨어 지정부트 프로그램 포함 1 파일 시스템에 대한 중요한 정보들을 저장하고 있다 파일시스템의 총 크기, inode 블록의 크기, 갱신날짜 가용 자료 블록 번호들에 대한 체인을 저장한 목록 가용 inode 블록 번호들에 대한 체인을 저장한 목록 2 n+2

파일 시스템의 내부 구조 (2) 슈퍼 블록의 필드 구성: 커널은 수퍼블록 내용 변경을 주기적으로 디스크에 저장 파일 시스템의 전체 크기 파일 시스템 내의 사용 가능한 자유 블록의 수 파일 시스템 내에서 사용 가능한 자유 블록의 리스트 inode 리스트의 크기 파일 시스템 내의 사용 가능한 자유 inode의 수 파일 시스템 내의 사용 가능한 자유 inode의 리스트 자유 inode 리스트의 다음 자유 inode의 인덱스 자유 블록 리스트와 자유 inode 리스트를 위한 잠금 필드들 커널은 수퍼블록 내용 변경을 주기적으로 디스크에 저장

파일 시스템의 내부 구조 (3) inode 블록 Inode 테이블을 저장하는 공간 디스크 inode의 필드 구성 : 파일 소유자 식별자 파일의 유형 파일 접근 허가 파일 접근 시간 파일에 대한 링크 수 파일 데이터의 디스크 주소 목록 파일 크기

파일 시스템의 내부 구조 (4) 데이터 블록 사용자 파일을 저장하는 공간 파일을 블록 단위로 저장 블록의 크기 – 보통 1024 바이트 1500 바이트의 파일을 저장할 때에 2개의 디스크 블록을 할당 하나의 파일을 저장하는 디스크 블록 목록은 해당 파일의 inode에 저장

파일의 내부 표현 (1) 파일의 내부 표현 : inode 파일의 내부적 표현은 inode(index node)에 의해 표현 파일 소유자 식별자 파일의 유형 파일 접근 허가 파일 접근 시간 파일에 대한 링크 수 파일 데이터의 디스크 주소 목록 파일 크기 하나의 파일은 여러 개의 이름을 가질 수 있고, 그 모든 이름들은 하나의 inode에 매핑되며 이를 link라고 함

파일의 내부 표현 (2) 파일의 내부 표현 : inode 파일 접근과 관련된 커널 데이터 구조: inode 테이블 – 파일에 대한 빠른 접근을 위해 파일시스테을 마운트할 때에 inode table을 커널 공간으로 로딩 파일 테이블 – 참조되고 있는 모든 파일을 관리하기 위해 전역적으로 정의한 테이블 사용자 파일티스크립터 테이블 – 하나의 프로세스가 참조하는 파일을 관린하기 위해 프로세스마다 할당하는 테이블

파일의 내부 표현 (3) 파일 참조 관련 테이블 : 사용자 파일 디스크립터 테이블 파일 테이블 inode 테이블 파일 테이블 인덱스 indoe 번호 inode 사용자 파일 디스크립터 테이블 파일 테이블 inode 테이블

파일 열기 (1) 파일 열기 : open

파일 열기 (2)

파일 열기 (3) 파일 열기 후의 자료 구조 변화 fd1=open("/etc/passwd",O_RDONLY); fd2=open("local",O_WRONLY); fd3=open("/etc/passwd",O_RDWR); 파일 열기 시스템 호출(open)이 실행되면 현재 파일 디스크립터 테이블에서 비어있는 인덱스 중에서 가장 작은 인덱스를 할당한다 파일 열기 후의 자료 구조 변화

파일 열기 (4) 표준 입출력 파일 하나의 프로세스가 생성되면 다음 세 개의 파일에 대해 자동적으로 열기를 수행한 후에 참조가 가능 표준 입력 파일 – keyboard 장치를 의미 표준 출력 파일 – console 장치를 의미 표준 에러 파일 – console 장치를 의미 파일 디스크립터 테이블의 첫번째 항목에서 세번째 항목까지는 표준 입출력 파일에 대한 파일 디스크립터를 저장 file descriptor 0 – 표준 입력 파일 file descriptor 1 – 표준 출력 파일 file descriptor 2 – 표준 에러 파일

파일 열기 (4) 파일 열기 예 : open 읽기(read)를 위한 파일 열기:  acctfd = open(account, O_RDONLY); 쓰기(write) 위한 파일 열기:  file = TMPFILE; fd   = open(file, O_WRONLY | O_CREAT| O_TRUNC, 0600); 추가(append)를 위한 파일 열기: logfd = open("/sys/log", O_WRONLY | O_APPEND | O_CREAT, 0600);

파일 열기 (5) 파일 열기 예 : open 읽기 및 쓰기를 위한 파일 열기 fdin = open(argv[1], O_RDWR); 쓰기 위한 새로운 파일 열기: 파일이 없으면 생성하고, 존재하면 비정상 종료한다. if((fdout = open(TMPFILE, O_WRONLY | O_CREAT | O_EXCL, 0666)) == -1) perror(TMPFILE);

파일 닫기 (1) 파일 닫기 : close

파일 닫기 (2) 파일 닫기 : close 커널은 파일 디스크립터와 해당되는 파일 테이블과 inode 테이블을 조작함으로써 close 작업을 한다. 파일 테이블 항의 참조 계수가 dup나 fork에 의해 1 이상이면 다른 사용자 파일 디스크립터가 그 파일 테이블 항을 참조하고 있는 것이다. 이때 커널은 참조 계수를 하나 감소시키고 close를 끝낸다. 파일 테이블 참조 계수가 1이면 커널은 그 항을 자유화하고 원래의 open 시스템 호출에서 할당된 inode를 방출한다.

파일 닫기 (3) 파일 닫기 : close 만약 다른 프로세스가 그 inode를 아직도 참조하고 있으면 커널은 그 inode 참조 계수를 하나 감소시키기만 한다. 그렇지 않으면 참조계수가 0이 되기 때문에 inode를 자유화한다. close 시스템 호출이 완료되면 사용자 파일 디스크립터 테이블은 비게 된다. 그 파일 디스크립터를 사용하려는 시도는 그 파일 디스크립터가 다른 시스템 호출로 다시 할당되기까지는 에러를 유발할 것이다. 프로세스가 exit할 때 커널은 활성 사용자 파일 디스크립터를 검사하여 내부적으로 모두 close한다. 그러므로 한 프로세스가 종료한 후에는 파일을 연(open) 채로 둘 수 없다.

파일 읽기 파일 읽기 : read

파일 쓰기 파일 쓰기 : write

예제 프로그램 (1) 예제 2-1: 표준 입력 파일(키보드)에서 데이터를 읽어 표준 출력 파일(화면)로 출력하는 것이다. 파일 디스크립터 0은 표준 입력, 1은 표준 출력을 의미한다. 일반적으로 표준 입출력 파일은 프로그램 수행 전에 열려(open) 있고, 터미널의 입출력 장치인 키보드와 화면(display)과 연관되어 있다. 프로그램 수행 시에 방향 키(< 혹은 >)를 이용하여 표준 입출력을 재지정(redirection)할 수 있다.

예제 프로그램 (2) #include <stdio.h> 2 main() {  2  main()  { char buf[BUFSIZ]; //표준 입력 파일에서 읽은 문자를 저장할 // 버퍼를 선언하며, BUFSIZ은 버퍼의크기를 // 나타내며 시스템의 헤더 파일 stdio.h에 // 이미 정의되어 있다. /* n은 read 함수 반환값인 입력 문자수를 저장할 변수 */  6       int n;      /*표준 입력 파일에서 읽은 문자의 수가 0보다 클 동안 읽어 표준 출력에 출력한다. */  8       while((n= read(0, buf,BUFSIZ)) > 0)  9           write(1, buf, n); 10       exit(0); }

예제 프로그램 (3) 예제 2-2 : cp #include <stdio.h> #include <fcntl.h> #define PMODE 0644 main(argc,argv) int argc; char *argv[]; { int fdin, fdout, n; char buf[BUFSIZ]; if(argc !=3) { fprintf(stderr, "Usage: %s filein fileout\n",argv[0]); exit(1); }

예제 프로그램 (4) if((fdin = open(argv[1],O_RDONLY)) == -1) { perror(argv[1]); exit(2); } if((fdout = open(argv[2],O_WRONLY | O_CREAT | O_TRUNC, PMODE)) == -1) { perror(argv[2]); exit(3); while((n = read(fdin, buf, BUFSIZ)) > 0) write(fdout,buf, n); exit(0);

파일의 임의 접근 (1) 파일의 임의 접근 : lseek

파일의 임의 접근 (2) 파일의 임의 접근 : lseek

파일의 임의 접근 (3) 파일의 임의 접근 : lseek rewind - 파일의 처음으로 read/write position을 설정한다. lseek (fd, 0L, 0); append - 파일의 끝으로 read/write position을 설정한다. lseek (fd, 0L, 2); update - 현재 위치의 데이터를 수정한다. read (fd, (char *) &record, sizeof (record)); /* update */ lseek (fd, (long) -sizeof (record), 1); write (fd, (char *) &record, sizeof (record));

파일의 임의 접근 (4) 파일의 임의 접근 : lseek record position - 현재 read/write할 파일의 위치를 얻는다. loc = lseek (fd, 0L, 1); increase file - 기록할 레코드의 크기만큼 파일의 크기가 증가한다. lseek (fd, (long) MAX * sizeof(record), 2); write (fd, (char *) &record, sizeof (record));

예제 프로그램 (1) 예제 2-3 : 사원 관리를 위한 파일을 생성하는 프로그램을 작성하라. 사원 개인의 레코드 구조는 아래와 같다.   #define  NAMESIZE 24   struct employee {                 /* 레코드의 type을 employee로 한다    */          char name [NAMESIZE];   /* 레코드의 첫번째 필드에 이름을 저장  */          int salary ;               /* 레코드의 두번째 필드에 급여를 저장  */          int pid ;                  /* 레코드에 프로세스 ID(6장 참조) 저장  */   };

예제 프로그램 (2) /* Header file: ex2-3.h */ #define NAMESIZE 24 struct employee { char name[NAMESIZE]; int salary; int pid; };

예제 프로그램 (3) #include <fcntl.h> #include <stdio.h> #include "ex2-3.h" main(argc,argv) int argc; char *argv[]; { int fd, open(), getpid(); struct employee record; if(argc < 2) { fprintf(stderr,"Usage: %s file\n",argv[0]); exit(1); }

예제 프로그램 (4) if((fd= open(argv[1],O_WRONLY | O_CREAT | O_EXCL, 0640))== -1) { perror(argv[1]); exit(2); } for(;;) { printf("Enter employee name <SPACE> salary: "); scanf("%s",record.name); if(record.name[0] == '.') break; scanf("%d",&record.salary); record.pid= getpid(); write(fd,(char *)&record, sizeof(record)); close(fd); exit(0);

예제 프로그램 (5) 예제 2-4 : 생성한 employeefile에서 lseek 함수를 이용하여 레코드 번호를 입력받아 해당 레코드를 출력하는 프로그램을 작성하라. 레코드 번호가 음수이면 프로그램을 종료한다.

예제 프로그램 (6) #include <fcntl.h> #include "ex2-3.h" main(argc,argv) int argc; char *argv[]; { int fd, recnum; struct employee record; if(argc < 2) { printf("Usage: %s file\n",argv[0]); exit(1); } if((fd= open(argv[1],O_RDONLY))== -1) { perror(argv[1]); exit(2);

예제 프로그램 (7) for(;;) { printf("Enter record number: "); scanf("%d", &recnum); if(recnum < 0) break; lseek(fd, (long) recnum*sizeof(record),0); if(read(fd,(char *) &record, sizeof(record))>0) printf("Employee: %s\tSalary: %d\n", record.name, record.salary); else printf("Record %d not found\n",recnum); } close(fd); exit(0);

예제 프로그램 (8) 예제 2-5 : 텍스트 파일을 읽어들여 lookup 테이블을 만들고 라인 번호를 입력으로 받아 해당 라인을 출력시키는 프로그램을 lseek 함수를 이용하여 작성하라. 라인 번호가 0보다 작으면 종료하며, lookup 테이블의 구조는 다음과 같다. static struct {        long offset;  /* 파일 내의 라인 offset을 저장한다 */        int  len;     /* 라인의 길이를 저장한다          */     } table [TABSIZE];

예제 프로그램 (9) #include <fcntl.h> #define TABSIZE 100 #define BUFSIZE 512 main(int argc, char *argv[]) { int n, i, entry, len; int fd, open(); long offset; static struct { int len; } table[TABSIZE]; char buf[BUFSIZE];

예제 프로그램 (10) if((fd = open(argv[1], O_RDONLY)) == -1) { perror(argv[1]); exit(1); } /* build look up table */ entry = 0; offset = 0; while((n = read(fd, buf, BUFSIZE)) > 0) { for(i=0; i < n; i++) { /* line length include '\n' */ table[entry].len++; offset++; if(buf[i] == '\n') table[++entry].offset = offset;

예제 프로그램 (11) #ifdef DEBUG for(i=0; i < entry; i++) printf("%d: %ld, %d\n", i+1, table[i].offset, table[i].len); #endif for(;;) { printf("Enter line number: "); scanf("%d",&n); if(--n < 0) break; lseek(fd, table[n].offset, 0); if(read(fd, buf, table[n].len) <= 0) continue; buf[table[n].len] = '\0'; printf("%s", buf); } close(fd); exit(0);

파일 디스크립터 복사 (1) 파일 디스크립터 복사 : dup

파일 디스크립터 복사 (2) 파일 디스크립터 복사 : dup 그림 2-4는 프로세스가 다음과 같은 순서로 시스템 호출을 수행한 결과를 보여준다. “/etc/passwd”를 열고(파일 디스크립터 3), 다시 “/etc/passwd”를 열고(파일 디스크립터 4), 그리고 “local”을 열고(파일 디스크립터 5), 마지막으로 파일 디스크립터 3을 dup하면 파일 디스크립터 6이 반환된다.

파일 디스크립터 복사 (3) 파일 디스크립터 복사 : dup

예제 프로그램 (1) 예제 2-6 : 표준 출력 파일 디스크립터(파일 디스크립터 1)를 닫고 dup로 화일 디스크립터를 복사한 후에 그것을 표준 출력 파일로 사용하여 표준 출력의 방향을 바꾸는 프로그램을 작성하라.

예제 프로그램 (2) #include <fcntl.h> #include <stdio.h> main(int argc,char *argv[]) { close(1); if(open(argv[1],O_WRONLY | O_CREAT | O_TRUNC, 0644) == -1) { perror(argv[1]); exit(1); } close(2); if(dup(1) == -1) { perror(argv[0]); exit(2); printf("first line to stdout (uses fd 1)\n"); fprintf(stderr,"first line to stderr (uses fd 2)\n"); printf("second line to stdout\n"); fprintf(stderr,"second line to stderr\n");

파일의 제어 (1) 파일의 제어 : fcntl

파일의 제어 (2) fcntl 함수 명령어(cmd)의 기능 :

파일의 제어 (3) fcntl 함수의 반환 값 :

예제 프로그램 (1) 예제 2-7 : 프로그램 2-3에서 이미 작성된 employee 파일의 끝에 새로운 레코드를 입력받아 추가하는 프로그램을 fcntl 함수를 이용하여 작성하라. 입력이 “.”이면 프로그램을 종료하도록 한다.

예제 프로그램 (2) #include <fcntl.h> #include "ex2-3.h" #define DUMMY 0 main(argc,argv) int argc; char *argv[]; { int fd, open(), getpid(), flags, fcntl(),pid; struct employee record; if(argc < 2) { printf("Usage: %s file\n",argv[0]); exit(1); } if((fd= open(argv[1],O_RDWR))== -1) { perror(argv[1]); exit(2); if((flags=fcntl(fd,F_GETFL, DUMMY)) == -1) { exit(3);

예제 프로그램 (3) flags |= O_APPEND; fcntl(fd, F_SETFL, flags); pid = getpid(); for(;;) { printf("Enter employee name : "); scanf("%s",&record.name); if(record.name[0] == '.') break; printf("Enter employee salary: "); scanf("%d",&record.salary); record.pid= pid; write(fd,(char *) &record, sizeof(record)); } close(fd);

예제 프로그램 (4) 예제 2-8 : 터미널 장치 파일로부터 5초 이내에 응답이 들어오면 프로그램을 계속 수행하고 그렇지 않으면 종료하는 프로그램을 fcntl 함수와 O_NDELAY 플래그(표 2-1 참조)를 이용하여 프로그램을 작성하라. 단, 5초간 입력을 기다릴 때는 sleep(5) 함수를 이용한다.

예제 프로그램 (5) #include <stdio.h> #include <string.h> #include <fcntl.h> main() { int fd, flags, open(), fcntl(); int i, n; char line[BUFSIZ]; if((fd = open("/dev/tty",O_RDONLY | O_NDELAY))== -1) { perror("/dev/tty"); exit(2); } printf("Enter your PIN within five seconds:\n"); sleep(5);

예제 프로그램 (6) if(read(fd,line,BUFSIZ) == 0) { printf("\n ====> Sorry.\n"); exit(1); } flags = fcntl(fd,F_GETFL,0); flags &= ~O_NDELAY; /* turn off delay flags */ fcntl(fd,F_SETFL,flags); printf("Enter your bank account number:\n"); read(fd,line, BUFSIZ); i = strlen(line); line[i++] = '\0'; printf("%s\n",line);