Unix 의 역사 Bell Lab의 Ken Tompson이 PDP-7 위에서 개발 (1969년) Dennis Ritchie가 참가하여 대부분을 C언어로 작성 Sixth Edition 개발 (1976년) 다른 기관이 사용할 수 있도록 배포한 최초의 버전 이후에 UNIX는

Size: px
Start display at page:

Download "Unix 의 역사 Bell Lab의 Ken Tompson이 PDP-7 위에서 개발 (1969년) Dennis Ritchie가 참가하여 대부분을 C언어로 작성 Sixth Edition 개발 (1976년) 다른 기관이 사용할 수 있도록 배포한 최초의 버전 이후에 UNIX는"

Transcription

1 고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 제1장 소개

2 Unix 의 역사 Bell Lab의 Ken Tompson이 PDP-7 위에서 개발 (1969년) Dennis Ritchie가 참가하여 대부분을 C언어로 작성 Sixth Edition 개발 (1976년) 다른 기관이 사용할 수 있도록 배포한 최초의 버전 이후에 UNIX는 크게 분류해서 연구용, AT&T 계열, BSD 계열로 분 화해서 발전 Seventh Edition (1979년): Bourne shell 개발 Eighth Edition (1985년): STREAMS 개발 2

3 AT&T UNIX System V, Release 3 개발 (1987년) : STREAMS 도입 System V, Release 4 개발 (1989년) : C/Korn shell, Job control, Symbolic link BSD UNIX BSD 4 개발 (1980년) : Job control, Reliable signal BSD 4.4 개발 (1993년) 기타 Mach Linux 3

4 Unix 표준화 동향 ANSI C (1989년) American National Standards Institute C 언어의 문법, 라이브러리와 헤더 파일의 표준을 제정 다양한 운영 체제 환경에서 C 프로그램의 호환성을 높이기 위함 POSIX (1988년) Portable Operating System Interface for Computer Environments 운영 체제가 제공해 주어야 하는 서비스를 정의 (POSIX Compliant) : 운영 체제의 인터페이스 표준 (POSIX.1 이라고도 함) , 등 XPG3 (1989년) X/Open Portability Guide 4

5 시스템 호출과 라이브러리 함수 System Calls well defined entry points directly into the kernel documented in section 2 of the UNIX man pages look like C functions which can be called from a user's program just need to include the appropriate header Library Functions the library function is often more elaborate than the system call, and usually invokes the system call 5

6 application code user process C library functions system calls kernel kernel hardware (harddisk ) 6

7 Error Handling #include <errno.h> extern int errno; UNIX 시스템 호출에서 에러가 발생하면 에러 발생을 의미하는 값이 리턴되고 (-1 or NULL) 전역 변수 errno 에 자세한 에러 상수 값이 설정 된다 errno 에 설정될 수 있는 에러 상수 값은 <errno.h> 에 정의되어 있다 7

8 #include <string.h> char *strerror(int errno); 파라미터 errno 값에 해당하는 에러 메시지를 리턴 #include <stdio.h> void perror(const char *msg); 표준 에러에 다음과 같은 순서로 메시지를 출력한다 msg 출력 문자열 ": " 출력 전역 변수 errno 값에 해당하는 에러 메시지 출력 8

9 고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 2장. 파일 입출력 (File I/O)

10 Contents I/O를 위한 kernel 자료구조 open() - 열기 creat() - 파일 생성 close() - 닫기 read() - 읽기 write() - 쓰기 lseek() - 이동 I/O Efficiency I/O 시스템 호출과 커널 자료구조 dup(), dup2() fcntl() Atomic operations 2

11 1. I/O를 위한 kernel 자료구조 process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2: fd 3:.... file table fd status flags current file offset v-node ptr fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size v-node information i-node information current file size 3

12 Process table entry 프로세스 테이블 (process table) 커널(kernel) 자료구조 프로세스 목록 프로세스 à 프로세스 테이블 항목 프로세스 테이블 항목 (Process table entry) 파일 디스크립터(file descriptor)의 배열을 포함 4

13 File descriptor 읽거나 쓰기 위해서 파일을 열면 (open 시스템 호출) 파일 디스크립터(file descriptor) 배열의 항목이 하나 할당되고 그 파일 디스크립터가 리턴된다 (배열의 인덱스가 리턴됨) 이후 이 파일에 대한 읽기/쓰기 시스템 호출(system call)에서는 이 파일 디스크립터를 파라미터로 전달해야 한다 파일 디스크립터 배열의 크기가 유한하므로 프로세스가 동시에 열 수 있는 파일의 수도 유한하다 파일 테이블 항목(file table entry)에 대한 포인터를 파일 디스크립 터는 가지고 있다. 5

14 File table entry 파일 테이블 (file table) 커널 자료구조 열려진 모든 파일 목록 열려진 파일 à 파일 테이블의 항목 파일 테이블 항목 (file table entry) 파일 상태 플래그 (read, write, append, sync, nonblocking, ) 파일의 현재 위치 (current file offset) v-node에 대한 포인터 6

15 v-node v-node의 내부 파일의 유형 함수들에 대한 포인터 배열 이 파일을 다루는데 사용되는 함수들 i-node 하드 디스크에 저장되어 있는 자료구조 파일에 대한 정보를 가지고 있음 소유자, 크기 파일이 위치한 장치 파일 내용 디스크 블럭에 대한 포인터 7

16 2. open() - 열기 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open (const char *pathname, int oflag, [ mode_t mode ]); 파일을 연다 파일이 없으면 경우에 따라 새로 만들어 질 수도 있다 리턴 값 : 파일 디스크립터(file descriptor), 실패하면 -1 pathname : 파일의 이름 mode : 파일의 access permission 값. 생략가능. 새로운 파일을 만드는 경우에만 사용됨 creat() 함수 설명 참조 8

17 open() 의 파라미터 두 번째 파라미터 oflag는 다음 상수들의 OR 이다 예) int fd; fd = open("afile", O_RDWR O_CREAT, S_IRUSR S_IWUSR ); 반드시 하나 지정해주어야 할 값 O_RDONLY : 읽기 모드, write 함수를 사용 할 수 없음 O_WRONLY : 쓰기 모드, read 함수를 사용 할 수 없음 O_RDWR : 읽고 쓰기 모드, read write 사용 가능 9

18 open() 의 파라미터 선택적 지정 가능 O_APPEND : 모든 write 된 데이터는 파일의 끝에 추가된다 O_CREAT : 파일이 없을 경우 파일을 생성한다 이때에만 세번째 인자 mode 가 필요하다 O_EXCL : 그 이름의 파일이 이미 있고 O_CREATE 를 지정한 경우 에러를 발생시킨다 O_TRUNC : 파일이 있는 경우에 기존 내용을 지우고 파일 크기를 0으로 만든다 O_NONBLOCK : nonblocking 모드로 입출력을 함 O_SYNC : 각 write 함수 호출은 디스크에 물리적으로 쓰여진 후 리턴한다 10

19 /* open.c */ #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include "error.h" int main() { int filedes; char fname[] = "afile"; if ((filedes = open (fname, O_RDWR)) == -1) error(fname); } printf("%s is opened.\n", fname); close(filedes); return 0; 11

20 3. creat () - 파일 생성 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int creat ( const char *pathname, mode_t mode ); 새로운 파일을 생성한다 리턴 값 : 파일 디스크립터, 실패하면 -1 pathname : 생성하고자 하는 파일의 이름 mode : 파일의 access permission 값 12

21 creat () 의 파라미터 다음의 두 함수 호출은 기능이 동일하다 fd = creat ( pathname, mode ); fd = open ( pathname, O_WRONLY O_CREAT O_TRUNC, mode); 두 번째 인자 mode는 다음 상수들의 OR 이다 S_IRUSR : user-read, 소유자의 읽기 허용 S_IWUSR : user-write, 소유자의 쓰기 허용 S_IXUSR : user-execute, 소유자의 실행 허용 S_IRGRP : group-read, 그룹 멤버의 읽기 허용 S_IWGRP : group-write, 그룹 멤버의 쓰기 허용 S_IXGRP : group-execute,그룹 멤버의 실행 허용 S_IROTH : other-read, 아무나 읽기 허용 S_IWOTH : other-write, 아무나 쓰기 허용 S_IXOTH : other-execute,아무나 실행 허용 13

22 4. close () - 닫기 #include <unistd.h> int close ( int filedes ); 작업이 끝난 후 파일을 닫는다. 리턴 값 : 성공하면 0, 실패하면 -1 filedes : 닫고자 하는 파일의 파일 디스크립터 파일을 닫지 않더라도 프로세스가 종료하면 모든 열려진 화일들은 자 동적으로 닫힌다 14

23 5. read () - 읽기 #include <unistd.h> ssize_t read ( int filedes, void *buf, size_t nbytes ); 파일에서 데이터를 읽는다 리턴 값: 성공하면 읽은 바이트 수 파일의 끝을 만나면 0 실패하면 -1 buff : 읽은 데이터를 저장할 메모리 nbytes : 메모리의 크기 15

24 read () - 읽기 읽을 데이터가 충분하면 한 번에 nbytes 만큼 읽는다. 읽을 데이터가 nbytes 보다 적은 경우 더 적게 읽기도 한다 파일의 끝에서 네트웍 입출력에서 size_t : unsigned integer ssize_t : signed integer 16

25 /* count.c -- 파일의 문자 수를 센다 */ #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include "error.h" #define BUFSIZE 512 int main() { char buffer[bufsize]; int filedes; ssize_t nread; long total = 0; if ((filedes = open("afile", O_RDONLY)) == -1) error("afile"); /* 파일의 끝에 도달할 때까지 반복 */ while( (nread = read(filedes, buffer, BUFSIZE)) > 0) total += nread; } close(filedes); printf ("total chars in afile: %ld\n", total); return 0; 17

26 6. write() - 쓰기 #include <unistd.h> ssize_t write (int filedes, const void *buf, size_t nbytes); 파일에 데이터를 쓴다 리턴 값 성공하면, 파일에 쓰여진 데이터의 바이트 수 실패하면, -1 buff : 쓸 데이터를 저장하고 있는 메모리 공간 nbytes : 쓸 데이터의 바이트의 수 18

27 /* copyfile.c -- 파일을 복사한다 */ #include <unistd.h> #include <fcntl.h> #define BUFSIZE 512 #define PERM 0644 int copyfile (const char *srcfile, const char *destfile) { int infile, outfile; ssize_t nread; char buffer[bufsize]; } if ((infile = open(srcfile, O_RDONLY)) == -1) return -1; if ((outfile = open(destfile, O_WRONLY O_CREAT O_TRUNC, PERM)) == -1) { close(infile); return -2; } while ((nread = read(infile, buffer, BUFSIZE)) > 0) { if (write(outfile, buffer, nread) < nread) { close (infile); close (outfile); return -3; } } close (infile); close (outfile); if (nread == -1) return -4; /* 마지막 읽기에서 에러 발생 */ return 0; 19

28 7. lseek() - 이동 #include <sys/types.h> #include <unistd.h> off_t lseek (int filedes, off_t offset, int whence ); 파일의 현재 위치(current file offset)를 이동 리턴 값: 성공하면 현재 위치를 리턴, 실패하면 -1 whence : 위치 기준점 SEEK_SET : 파일의 시작점을 기준으로 이동 SEEK_CUR : 현재 위치를 기준으로 이동 SEEK_END : 파일의 끝을 기준으로 이동 offset : 기준점에서의 상대적인 거리 (byte 단위) SEEK_CUR, SEEK_END 와 같이 쓰일 때는 음수도 가능 20

29 lseek() 이동 파일의 현재 위치를 임의의 위치로 이동한다 파일의 현재 위치(current file offset) 파일에 대한 읽기/쓰기는 파일의 현재 위치에서 실행된다 파일을 처음 열면 현재 위치는 0 즉 파일의 시작이다 읽기/쓰기 후 파일의 현재 위치는 읽기/쓰기 한 byte 수 만큼 저 절로 뒤로 이동된다 lseek()를 사용하여 임의의 위치로 파일의 현재 위치를 이동할 수 있다 21

30 /* lseek.c */ #include <unistd.h> int main() { if (lseek(stdin_fileno, 0, SEEK_CUR) == -1) printf("cannot seek\n"); else printf("seek OK\n"); return 0; } 22

31 #include <unistd.h> /* lseek1.c */ #include <fcntl.h> #include "error.h" char char buf1[] = "abcdefghij"; buf2[] = "ABCDEFGHIJ"; int main() { int fd; } if ( (fd = creat("file.hole", S_IRUSR S_IWUSR S_IRGRP S_IROTH)) < 0) error("file.hole"); if (write(fd, buf1, 10)!= 10) /* offset now = 10 */ error("buf1"); if (lseek(fd, 40, SEEK_SET) == -1) /* offset now = 40 */ error("lseek"); if (write(fd, buf2, 10)!= 10) /* offset now = 50 */ error("buf2"); return 0; 23

32 lseek1.c 의 출력 파일 file.hole의 내용 a b c d e f g h i j 10 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 20 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 30 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 40 A B C D E F G H I J 24

33 #include <sys/types.h> /* lseek2.c */ #include <unistd.h> #include <fcntl.h> #include "error.h" int main() { int fd; off_t fsize; char buf[11]; } if((fd=open("file.hole", O_RDONLY)) < 0) error("file.hole"); fsize = lseek(fd, 0, SEEK_END); printf("size: %lu\n", fsize); lseek(fd, 40, SEEK_SET); read(fd, buf, 10); buf[10] = 0; puts(buf); return 0; 25

34 8. I/O Efficiency 디스크는 메모리에 비해서 상대적으로 매우 느린 장치 성능을 위해서는 디스크 I/O의 횟수를 줄이는 것이 바람직 작은 양을 여러번 I/O 하는 것 보다 많은 양을 I/O 하여 횟수를 줄이는 것이 좋다 write1.c 에서 BUFFSIZE 값을 변경하며 수행 시간을 측정 8192 까지는 BUFFSIZE 가 클수록 성능이 향상 8192 보다 큰 경우는 성능에 변화가 없다 26

35 Berkeley fast filesystem 의 I/O 단위는 8192 BUFFSIZE 가 8192 보다 큰 경우 내부 I/O 의 단위는 8192 이므로 성능의 향상이 없다 BUFFSIZE 가 8192의 배수가 아닌 경우는 오히려 8192 인 경우보다 I/O 횟수가 많아져 성능이 하락할 수 있다 27

36 #include <sys/types.h> /* write1.c */ #include <sys/stat.h> #include <fcntl.h> #include "error.h" #define BUFFSIZE 512 #define FILESIZE (100 * 1024 * 1024) #define COUNT FILESIZE / BUFFSIZE int main() { int i, fd; char buf[buffsize]; } memset(buf, '.', BUFFSIZE); if ((fd = creat("file.write", S_IRUSR S_IWUSR)) < 0) error("file.write"); for (i=0; i < COUNT; ++i) write(fd, buf, BUFFSIZE); close(fd); return 0; 28

37 BUFFSIZE User CPU (seconds) System CPU (seconds) Clock time (seconds) #loops , , ,857, ,428, ,214, ,107, ,553, ,276, ,638, , , ,800 1, ,400 2, ,200 4, ,600 8, ,800 16, ,400 32, ,200 65, , ,

38 9. I/O 시스템 호출과 커널 자료구조 process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2: fd 3:.... file table fd status flags current file offset v-node ptr fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size v-node information i-node information current file size 30

39 read / write 시스템 호출 file table entry 의 current file offset 값이 읽은/쓰여진 바이 트 수 만큼 증가 write 후 file table entry의 current file offset 이 i-node의 current file size 보다 크면 current file size 값이 증가 파일이 O_APPEND 플래그로 오픈되었으면 file table entry의 file status flags 에 해당 플래그가 세팅됨 모든 write 시스템 호출은 먼저 current file offset을 i-node 의 current file size 값 으로 설정한 후 수행된다 따라서 모든 write 는 파일의 끝에 덧붙여진다 31

40 lseek 시스템 호출은 file table entry 의 current file offset 값을 변경 disk I/O 는 없음 lseek에서 SEEK_END 를 사용하여 파일의 끝으로 이동하면 file table entry 의 current file offset 값은 i-node 의 current file size 값으로 설정됨 32

41 10. dup(), dup2() #include <unistd.h> int dup (int filedes); int dup2 (int filedes, int filedes2); 사용 중인 파일 디스크립터의 복사본을 만듦 dup() 는 새 파일 디스크립터 번호가 할당됨 dup2() 는 filedes2 를 사용 filedes2 가 이미 사용 중이면 먼저 close 한다 리턴 값: 성공하면 복사된 새 파일 디스크립터, 실패하면 -1 dup() 함수는 할당 가능한 가장 작은 번호를 리턴한다. dup2() 함수는 filedes2 를 리턴한다. 33

42 파일 공유 1 process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2: fd 3:.... file table fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size newfd = dup(1); or newfd = dup2(1,3); 호출 후 리턴 값은 3 file table 의 current file offset 와 fd status flags 는 공유됨 file descriptors의 fd flags 는 공유안됨 34

43 #include <fcntl.h> /* dup.c */ #include <unistd.h> #include "error.h" int main() { int fd1, fd2, n; char buf[11]; } if ((fd1 = open("afile", O_RDONLY)) < 0) error("afile"); if ((fd2 = dup(fd1)) < 0) error("dup"); n = read(fd1, buf, 10); buf[n] = 0; puts(buf); n = read(fd2, buf, 10); buf[n] = 0; puts(buf); close(fd1); close(fd2); return 0; 35

44 파일 공유 2 process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2: fd 3:.... file table fd status flags current file offset v-node ptr fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size 같은 파일에 대하여 open() 을 두번 호출한 경우 current file offset 은 공유되지 않는다 36

45 #include <fcntl.h> /* open2.c */ #include <unistd.h> int main() { int fd1, fd2, n; char buf[11]; fd1 = open("afile", O_RDONLY); fd2 = open("afile", O_RDONLY); if (fd1 < 0 fd2 < 0) error("afile"); } n = read(fd1, buf, 10); buf[n] = 0; puts(buf); n = read(fd2, buf, 10); buf[n] = 0; puts(buf); close(fd1); close(fd2); return 0; 37

46 파일 공유 3 process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2:.... file descriptors fd 0: fd flags ptr fd 1: fd 2:.... file table fd status flags current file offset v-node ptr fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size 두 프로세스(process)에서 같은 파일을 연 경우 38

47 dup(), dup2() 의 용도 표준 입출력의 redirection 표준 입출력 대상을 파일로 바꿈 표준 입출력의 파일 디스크립터 #include <unistd.h> #define STDIN_FILENO 0 /* 표준 입력 */ #define STDOUT_FILENO 1 /* 표준 출력 */ #define STDERR_FILENO 2 /* 표준 에러 */ 39

48 #include <unistd.h> /* dup1.c */ #include <fcntl.h> #include <stdio.h> int main() { int fd; } if((fd = creat("afile", S_IRUSR S_IWUSR)) == -1) error("afile"); printf("this is displayed on the screen.\n"); dup2(fd, STDOUT_FILENO); printf("this is written into the redirected file.\n"); return 0; 40

49 #include <unistd.h> /* dup2.c */ #include <fcntl.h> #include <stdio.h> #include "error.h" int main() { int fd; } if((fd = creat("afile", S_IRUSR S_IWUSR)) == -1) error("afile"); printf("this is displayed on the screen.\n"); close(stdout_fileno); dup(fd); printf("this is written into the redirected file.\n"); return 0; 41

50 11. fcntl() #include <sys/types.h> #include <fcntl.h> #include <unistd.h> int fcntl (int filedes, int cmd, /* int arg */ ); 열려져 있는 파일의 속성을 알아내거나 속성을 변경한다. 리턴 값: cmd 값에 따라 다름, 실패하면 -1 42

51 fcntl() 의 두번째 파라미터 F_DUPFD 파일 디스크립터를 복사 dup() dup2() 와 유사함 세 번째 인수 보다 크거나 같은 값 중, 가장 작은 미사용의 값을 리턴 F_GETFD : file descriptor의 file descriptor flags 를 리턴 F_SETFD : file descriptor flags 를 설정 F_GETFL : file table 의 file status flags 를 리턴 F_SETFL : file status flags 를 설정 43

52 file table 의 file status flags File status flag O_RDONLY O_WRONLY O_RDWR O_APPEND O_NONBLOCK O_SYNC O_ASYNC Description open for reading only open for writing only open for reading and writing append on each write nonblocking mode wait for writes to complete asynchoronouse I/O (4.3 BSD only) F_SETFL 는 O_APPEND O_NONBLOCK O_SYNC O_ASYNC 만을 설정할 수 있음 44

53 F_GETOWN asynchronous I/O ownership 을 리턴 SIGIO, SIGURG 시그널을 받는 프로세스 ID를 리턴 F_SETOWN asynchronous I/O ownership 을 설정 SIGIO, SIGURG 시그널을 받는 프로세스 ID를 설정 45

54 #include <sys/types.h> /* fileflags.c */ #include <fcntl.h> #include "error.h" int main() { int accmode, val; int fd; fd = open("afile", O_WRONLY O_APPEND); if (fd == -1) error("afile"); if ((val = fcntl(fd, F_GETFL, 0)) < 0) error("fcntl"); accmode = val & O_ACCMODE; if (accmode == O_RDONLY) printf("read only"); else if (accmode == O_WRONLY) printf("write only"); else if (accmode == O_RDWR) printf("read write"); else printf("unknown access mode"); } if (val & O_APPEND) printf(", append"); if (val & O_NONBLOCK) printf(", nonblocking"); if (val & O_SYNC) printf(", synchronous writes"); putchar('\n'); return 0; 46

55 Asynchronous Write UNIX 에서 write 는 asynchronous write 이다 데이터가 디스크에 쓰여지길 기다리지 않고 쓰여질 데이터를 큐(queue)에 등록하고 바로 리턴한다 큐에 등록된 데이터는 나중에 디스크에 쓰여진다 synchronous write write 호출은 데이터가 실제로 디스크에 쓰여진 후 리턴한다 asynchronous write에 비해서 clock time 이 증가한다 file table 의 file status flags 에서 O_SYNC 플래그를 설정 47

56 #include <sys/types.h> /* write2.c */ #include <sys/stat.h> #include <fcntl.h> #include "error.h" #define BUFFSIZE 8192 #define FILESIZE (100 * 1024 * 1024) #define COUNT FILESIZE / BUFFSIZE void set_fl(int fd, int flags) /* flags are file status flags to turn on */ { int val; } if ( (val = fcntl(fd, F_GETFL, 0)) < 0) error("fcntl F_GETFL error"); val = flags; /* turn on flags */ if (fcntl(fd, F_SETFL, val) < 0) error("fcntl F_SETFL error"); 48

57 int main() { int i, fd; char buf[buffsize]; } memset(buf, '.', BUFFSIZE); if ((fd = creat("file.write", S_IRUSR S_IWUSR)) < 0) error("creat erroror"); set_fl(fd, O_SYNC); /* turn on the synchronous-write flag */ for (i=0; i < COUNT; ++i) write(fd, buf, BUFFSIZE); close(fd); return 0; 49

58 BUFFSIZE User CPU (seconds) System CPU (seconds) Clock time (seconds) #loops asynchrohous 8, ,800 synchrohous 8, ,800 위 결과에서 볼 수 있듯이 synchronous write 가 훨씬 더 느림 데이터베이스 시스템처럼 실제로 데이터가 디스크에 기록되었는지 여 부가 중요한 경우에 사용됨 50

59 12. Atomic operations 복수개의 스텝으로 구성된 operation으로 모든 스텝이 성공적으로 수행되거나, 전부 실패하거나 둘 중의 하나 부분적으로 성공하고 부분적으로 실패하는 경우는 없음 스텝이 실행되는 중간에 다른 operation 의 개입으로 영향을 받지 않 는다 51

60 Atomic operation 의 예 1 A) fd = open(, O_WRONLY O_APPEND); write(fd, buff, 100); B) fd = open(, O_WRONLY); lseek(fd, 0L, SEEK_END); write(fd, buff, 100); A)와 B)의 기능은 같다 step1) 먼저 current file offset 이 파일의 끝으로 이동한 후 step2) buff를 쓴다 52

61 A) 의 경우 step1) 과 step2) 는 write 시스템 호출 내부에서 실행 step1) 과 step2) 는 atomic operation B) 의 경우 step1) 은 lseek 시스템 호출 step2) 는 write 시스템 호출 step1) 과 step2) 는 atomic operation 이 아님 53

62 두 개 이상의 프로세스가 공유 파일에 대해서 write 하는 경우 10절의 파일 공유 3 에 해당 예) 여러 프로세스가 동일한 log 파일에 메시지를 추가하는 경우 A) 의 경우 Process 1 Process 2 write - step1 - step2 write - step1 - step2 54

63 B) 의 경우 Process 1 Process 2 lseek - step1 lseek step2 write step2 write step2 Process 1 과 Process 2 의 lseek step1 는 동일한 current file offset 을 설정함 Process 2 의 write step2 는 Process 1 의 write 를 덮어 쓰게 됨 55

64 Atomic operation 의 예 2 A) fd = open(pathname, O_WRONLY O_CREAT, mode); B) if ((fd = open(pathname, O_WRONLY)) < 0) { if (errno == ENOENT) fd = creat(pathname, mode); } A) 와 B) 의 기능은 동일 A) 는 atomic operation 56

65 고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 3장. 파일시스템 (Filesystem)

66 Contents 1. stat(), fstat(), lstat() 2. File Type 3. File Access Permissions 4. access() 5. umask() 6. chmod(), fchmod() 7. Sticky bit 8. chown(), fchown(), lchown() 9. truncate(), ftruncate() 10. Filesystem 11. link() unlink() remove() rename() 12. Symbolic Links 13. File Times 14. Directory 15. sync(), fsync() 2

67 1. stat(), fstat(), lstat() #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 구조체에 얻어 온다 리턴 값 : 성공하면 0, 실패하면 -1 buf : stat 구조체에 대한 포인터로 lstat()는 심볼릭 링크(symbolic link)가 가르키는 파일이 아니고 심볼릭 링크 자체에 대한 정보를 얻는다 3

68 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 allocated */ }; 4

69 st_atime : 마지막으로 파일의 데이터를 읽은 시각 st_mtime : 마지막으로 파일의 데이터를 수정한 시각 st_ctime : 파일의 데이터가 아니고 이름이나 권한 같은 상태를 변경한 시각 st_blksize : 가장 효율적인 I/O 블럭 크기 (2장 8절 I/O 성능 참고, 8192 bytes) st_blocks : 파일이 차지하고 있는 공간의 크기를 512 byte 블럭의 수로 5

70 2. File Type 보통 파일 (Regular file) 데이터를 포함하고 있는 텍스트 또는 이진 화일 디렉토리 파일 (Directory file) 파일의 이름들과 파일 정보에 대한 포인터들을 포함 문자 특수 파일 (Character special file) 시스템에 장착된 어떤 장치를 가리키는 파일 문자 단위로 데이터를 전송하는 장치 블록 특수 파일 (Block special file) 시스템에 장착된 어떤 장치를 가리키는 파일 블럭 단위로 데이터를 전송하는 장치 6

71 FIFO 프로세스 간 통신에 사용되는 파일 named pipe 라고도 불림 소켓 (socket) 네트웍을 통한 프로세스 간 통신에 사용되는 파일 심볼릭 링크 (Symbolic link) 다른 파일을 가리키는 포인터 역할을 하는 파일 7

72 파일 타입 검사 파일 타입을 검사하는 매크로 함수 #include <sys/stat.h> S_ISREG() : 정규 파일 S_ISDIR() : 디렉토리 파일 S_ISCHR() : 문자 특수 파일 S_ISBLK() : 블록 특수 파일 S_ISFIFO() : pipe 또는 FIFO S_ISLNK() : 심볼릭 링크 S_ISSOCK() : 소켓 해당 종류의 파일이면 1, 아니면 0 을 리턴 stat 구조체의 st_mode 값을 검사함 8

73 파일 타입 상수 #include <sys/stat.h> S_IFREG : 정규 파일 S_IFDIR : 디렉토리 파일 S_IFCHR : 문자 특수 파일 S_IFBLK : 블록 특수 파일 S_IFFIFO : pipe 또는 FIFO S_IFLNK : 심볼릭 링크 S_IFSOCK : 소켓 S_ISxxx() 매크로 함수는 S_IFxxx 상수 값의 설정 여부를 판단 9

74 #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); 10

75 [실행 결과] % a.out /etc /dev/ttya /bin a.out /etc: directory /dev/ttya: symbolic link /bin: symbolic link a.out: regular symbolic link 에 대한 정보도 얻기 위해서 stat() 대신 lstat() 를 사용 11

76 3. File Access Permissions file access permission bits (stat 구조체의 st_mode 의 값) #include <sys/stat.h> st_mode mask S_IRUSR S_IWUSR S_IXUSR S_IRGRP S_IWGRP S_IXGRP S_IROTH S_IWOTH S_IXOTH Meaning user-read user-write user-execute group-read group-write group-execute other-read other-write other-execute 12

77 UNIX 명령어 chmod file access permission 설정 stat 구조체의 st_mode UNIX 명령어 chown file 소유 user id 설정 stat 구조체의 st_uid UNIX 명령어 chgrp file 소유 group id 설정 stat 구조체의 st_gid 13

78 read 권한이 있어야 O_RDONLY O_RDWR 을 사용하여 파일을 열 수 있다 write 권한이 있어야 O_WRONLY O_RDWR O_TRUNC 을 사용하여 파일을 열 수 있다 디렉토리에 write 권한과 execute 권한이 있어야 그 디렉토리에 파일을 생성할 수 있고 그 디렉토리의 파일을 삭제할 수 있다 삭제할 때 그 파일에 대한 read write 권한은 없어도 됨 14

79 파일이 포함된 모든 상위 디렉토리에 대해 execute 권한이 있어야 그 파일을 열 수 있다 디렉토리에 대한 read 권한이 있어야 디렉토리 안에 들어 있는 파일 이름 목록을 읽을 수 있다 디렉토리에 대한 write 권한이 있어야 디렉토리에 파일을 생성 삭제 할 수 있다 디렉토리에 대한 execute 권한이 있어야 그 디렉토리나 그 하위 디렉 토리에 있는 파일을 열 수 있다 15

80 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 가 사용되고 다음 슬라이드와 같은 경우만 예외 16

81 S_ISUID 와 S_ISGID stat 구조체의 st_mode 의 비트 S_ISUID : set-user-id S_ISGID : set-group-id st_mode 의 S_ISUID 비트가 설정된 실행 파일을 실행한 경우 그 실행 파일이 실행된 프로세스의 effective user ID 는 real user ID 가 아니고 st_uid : 그 실행 파일의 소유자 user ID st_mode 의 S_ISGID 비트가 설정된 실행 파일을 실행한 경우 그 실행 파일이 실행된 프로세스의 effective group ID 는 st_gid : 그 실행 파일의 소유자 group ID 17

82 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 Jul /bin/passwd* 18

83 4. access() #include <unistd.h> int access (const char *pathname, int mode ); real user ID와 real group ID로 파일의 permission 체크 리턴 값: 성공하면 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 19

84 #include <sys/types.h> #include <fcntl.h> #include <unistd.h> #include "error.h" int main(int argc, char *argv[]) { if (argc!= 2) halt("usage: a.out <pathname>"); if (access(argv[1], R_OK) < 0) error("r_ok"); else printf("read access OK\n"); if (open(argv[1], O_RDONLY) < 0) error("o_rdonly"); else printf("open for reading OK\n"); } return 0; 20

85 5. umask() #include <sys/types.h> #include <sys/stat.h> mode_t umask (mode_t cmask ); 파일 생성 시 적용할 마스크 값 설정 리턴 값: 기존의 마스크 값 cmask: bitwise OR S_IRUSR, S_IWUSR, S_IXUSR S_IRGRP, S_IWGRP, S_IXGRP S_IROTH, S_IWOTH, S_IXOTH umask() 호출 후 파일을 생성할 때는 cmask 에 설정된 bit 들이 꺼진 다 UNIX 명령어 : umask 참조 21

86 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include "error.h" int main(void) { umask(0); if (creat("foo", S_IRUSR S_IWUSR S_IRGRP S_IWGRP S_IROTH S_IWOTH) < 0) error("foo"); } umask(s_irgrp S_IWGRP S_IROTH S_IWOTH); if (creat("bar", S_IRUSR S_IWUSR S_IRGRP S_IWGRP S_IROTH S_IWOTH) < 0) error("bar"); return 0; 22

87 [실행 결과] % a.out % ls -al foo bar -rw lsj 없음 0 Jul 21 11:54 bar -rw-rw-rw- 1 lsj 없음 0 Jul 21 11:54 foo % umask 22 23

88 6. 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 24

89 #include <sys/types.h> #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; 25

90 [실행 결과] $ ls -l foo bar -rw lsj 없음 0 Jul 21 12:04 bar -rw-rw-rw- 1 lsj 없음 0 Jul 21 12:04 foo $ a.out $ ls -l foo bar -rw-r--r-- 1 lsj 없음 0 Jul 21 12:04 bar -rw-rwlrw- 1 lsj 없음 0 Jul 21 12:04 foo 26

91 foo 파일의 set-group-id bit 를 켜고, group-execute bit 를 끄다 à mandatory record locking 활성화 à ls 의 출력에서 group-execute permisson 문자가 'l' ls 출력에서 foo 와 bar 의 날짜가 변경되지 않는다 chmod 는 stat 구조체의 st_ctime 만을 변경 ls 는 stat 구조체의 st_mtime 을 출력 27

92 chmod() 의 mode 상수 값 #include <sys/stat.h> mode S_ISUID S_ISGID S_ISVTX S_IRWXU S_IRUSR S_IWUSR S_IXUSR S_IRWXG S_IRGRP S_IWGRP S_IXGRP S_IRWXO S_IROTH S_IWOTH S_IXOTH Description set-user-id on execution set-group-id on execution saved-text (sticky bit) read, write, and execute by user (owner) read by user (owner) write by user (owner) execute by user (owner) read, write, and execute by group read by group write by group execute by group read, write, and execute by other (world) read by other (world) write by other (world) execute by other (world) 28

93 7. Sticky bit (S_ISVTX) S_ISVTX 비트의 기원 sticky bit 가 설정된 실행 파일은 프로그램의 종료 후 swap 영영 에 저장하여 프로그램의 재실행 시 빠르게 메모리에 로드할 수 있도록 함 자주 사용되는 실행 파일의 경우에 설정 초기의 느린 디스크 입출력 속도 때문에 사용되었으나 현재는 가상 메모리 기법과 빠른 파일 시스템으로 인하여 이런용도로 사용되지 않는다 29

94 현재 시스템에서 Sticky bit 는 특수한 디렉토리를 설정하는데 사용 파일을 지우거나 이름을 바꾸려고 할 때 보통의 디렉토리는 사용자가 디렉토리에 대한 쓰기 권한만 있으면 가능 Sticky bit 가 설정된 디렉토리는 파일의 소유자이거나, 디렉토리의 소유자이거나, 슈퍼 유저인 경 우에만 그 디렉토리의 파일을 지우거나 이름을 바꿀 수 있다. Sticky bit 는 슈퍼 유저만 설정할 수 있다 30

95 Sticky bit 디렉토리의 예: /tmp 임시 파일 디렉토리 모든 사용자에게 쓰기 권한이 있어서 파일을 만들 수 있다 그러나 자신의 소유 파일만 삭제하거나 이름을 바꿀 수 있다 $ ls ld /tmp drwxrwxrwt 7 root sys 5628 Jul 21 12:50 /tmp/ à ls 의 출력에서 other-execute permisson 문자가 't' 31

96 8. chown(), fchown(), lchown() #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()은 심볼릭 링크(symbolic link)가 가르키는 파일이 아니고 심볼릭 링크 자체를 변경한다 Berkeley 기반 시스템에서는 super-user만 변환 가능 System V 계열 시스템은 일반 사용자도 변경 가능 (_POSIX_CHOWN_RESTRICTED 값에 의해 결정) 32

97 9. 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 33

98 10. Filesystem disk drive partition partition partition i-list directory blocks and data blocks boot block(s) super block i-node i-node... i-node 34

99 i-node 하드 디스크에 저장되어 있는 자료구조 파일에 대한 정보를 가지고 있음 file type access permission bits file size pointers to data blocks for the file stat 구조체의 필드는 i-node 에서 읽어온다 35

100 directory blocks and data blocks i-list data block data block directory block data block directory block i-list i-node i-node... i-node directory block i-node number filename directory block i-node number filename 36

101 directory block 은 파일 목록을 저장 파일 이름과 그 파일의 i-node number hard link directory block 의 파일 이름과 i-node 와의 연결 i-node number 로 연결 UNIX 명령어 ln 참고 i-node number filesystem 의 i-list 에서 i-node 의 일련번호 따라서 hard link 는 같은 filesystem 내부에서만 가능 37

102 symbolic link 파일의 내용(data block의 내용)은 링크 대상 파일의 pathname 예) lrwxrwxrwx 1 root 7 Sep 25 07:14 lib -> usr/lib 파일 이름은 lib 파일 내용은 usr/lib 파일 크기 7 bytes UNIX 명령어 ln s 참고 i-node 의 link count stat 구조체의 st_nlink 이 i-node 를 가르키는 directory entry 수 앞 슬라이드 그림에서 두 directory entry 는 동일한 i-node 를 가르키므로 link count 는 2 38

103 파일의 삭제 directory block 에서 파일을 삭제하면 i-node 의 link count 가 하나 감소 link count 가 0 에 도달하면 그 파일의 i-node 와 data block 이 삭제됨 파일의 이동 UNIX 명령어 mv 파일의 data block 이나 i-node 의 변화는 없이 directory entry 만 변경됨 39

104 directory blocks and data blocks i-list data block data block directory block directory block i-node 0 i-node 1267 i-node 2549 directory block directory block 1267 i-node testdir 40

105 testdir 디렉토리의 i-node number는 2549 testdir의 부모 디렉토리 i-node number는 1267 i-node 2549의 link count는 최소 2 i-node 1267의 link count는 최소 3 41

106 11. link() #include <unistd.h> int link (const char *existingpath, const char *newpath ); 이미 존재하는 파일(existingpath)에 대해서 새로운 디렉토리 항목 (newpath)을 만든다 리턴 값: 성공하면 0, 실패하면 -1 42

107 hard link 가 만들어짐 같은 i-node를 가리키는 directory entry 가 하나 더 만들어짐 그 i-node의 link count 가 하나 증가 hard link는 하나의 파일시스템 내부에서만 가능 43

108 unlink() #include <unistd.h> int unlink (const char *pathname); 파일의 link count를 감소 시킴 리턴 값: 성공하면 0, 실패하면 -1 unlink()는 directry entry를 지우며, 파일의 link count를 1 감소 시킨다 link count 가 0이 되면, 파일을 디스크에서 제거한다. i-node와 data block 삭제 44

109 다른 프로세스가 사용중인 파일이 삭제되는 것을 방지하기 위해 link count가 0에 도달했더라도 그 파일을 open 한 프로세스의 수가 0 이상이면 삭제하지 않는다 파일이 close 될 때 kernel은 그 파일을 open 한 프로세스 수가 0 인 지 확인하고, 0 일 경우 link count가 0 인지 확인하고 삭제한다 45

110 #include <sys/types.h> /* unlink.c */ #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include "error.h" int main() { int fd, len; char buf[20]; fd = open("tempfile", O_RDWR O_CREAT O_TRUNC, 0666); if (fd == -1) error("open1"); unlink("tempfile"); len = write(fd, "How are you?", 12); if (len!= 12) error("write"); lseek(fd, 0L, SEEK_SET); len = read(fd, buf, sizeof(buf)); if (len < 0) error("read"); buf[len] = '\0'; printf("%s\n", buf); close(fd); } fd = open("tempfile", O_RDWR); if (fd == -1) error("open2"); close(fd); return 0; 46

111 remove() #include <unistd.h> int remove (const char *pathname); 파일의 link count를 감소 시킴 리턴 값: 성공하면 0, 실패하면 -1 pathname이 파일이면 unlink()와 같은 일을 하고, 디렉토리이면 rmdir()과 같은 일을 한다 47

112 rename() #include <unistd.h> int rename (const char *oldname, const char *newname ); 파일이나 디렉토리의 이름을 바꾼다. 리턴 값: 성공하면 0, 실패하면 -1 newname이 이미 존재하는 경우 oldname이 파일을 가리키고 newname이 파일로서 존재할 때, 기존 을 파일을 덮어 쓴다. oldname이 디렉토리를 가리키고 newname이 비어 있는 디렉토리일 때, 기존의 디렉토리를 덮어 쓴다. 48

113 12. Symbolic Links 심볼릭 링크(symbolic link)는 파일에 대한 간접적인 포인터 실제 파일에 대한 경로를 저장하고 있다 링크의 한계점을 극복 링크는 단일 파일시스템에서만 허용된다 디렉토리에 대한 링크는 수퍼 유저만 만들 수 있다 49

114 파일을 다루는 함수를 사용할 때 심볼릭 링크를 자체를 다루는지 아 니면 링크된 대상 파일을 다루는지 심볼릭 링크 자체를 다루는 함수 lchown, lstat, readlink, remove, rename, unlink 등 링크된 대상 파일을 다루는 함수 access, chdir, chmod, chown, creat, exec, link, mkdir, mkfifo, open, opendir, pathconf, stat, truncate 등 50

115 symlink() #include <unistd.h> int symlink (const char *actualpath, const char *sympath ); 심볼릭 링크를 만든다 심볼릭 링크 파일의 내용은 actualpath 심볼릭 링크 파일의 크기는 actualpath 문자열의 길이 리턴 값: 성공하면 0, 실패하면 -1 actualpath : 실제 파일 sympath : 만들 심볼릭 링크의 이름 51

116 readlink() #include <unistd.h> int readlink (const char *pathname, char *buf, int bufsize ); 심볼릭 링크 파일의 내용을 읽는 함수 symlink() 에서 저장된 actualpath 가 buf에 채워진다 null 문자는 채워지지 않는다 리턴 값: 성공하면 읽은 문자열의 길이, 실패하면 -1 심볼릭 링크를 open 으로 열면 링크된 대상 파일이 열린다 52

117 13. File Times stat 구조체의 st_atime 파일의 데이터가 마지막으로 읽혔던 시간 read() 호출 stat 구조체의 st_mtime 파일의 데이터가 마지막으로 변경된 시간 write () 호출 stat 구조체의 st_ctime 파일의 stat 구조의 내용이 마지막으로 변경된 시간 chmod(), chown() 호출 UNIX 명령어 ls 의 l u c 옵션 참고 53

118 utime() #include <sys/types.h> #include <utime.h> int utime (const char *pathname, const struct utimbuf *times ); 파일의 최종 접근 시간과 최종 변경 시간을 조정한다. times가 NULL 이면, 현재시간으로 설정된다. 리턴 값: 성공하면 0, 실패하면 -1 UNIX 명령어 touch 참고 54

119 struct utimbuf { time_t actime; /* access time */ time_t modtime; /* modification time */ } 각 필드는 :00 부터 현재까지의 경과 시간을 초로 환산한 값 55

120 #include <sys/types.h> /* utime.c */ #include <sys/stat.h> #include <fcntl.h> #include <utime.h> #include "error.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 */ error(argv[i]); if (open(argv[i], O_RDWR O_TRUNC) < 0) /* truncate */ error(argv[i]); timebuf.actime = statbuf.st_atime; timebuf.modtime = statbuf.st_mtime; if (utime(argv[i], &timebuf) < 0) /* reset times */ error(argv[i]); } return 0; 56

121 앞 슬라이드의 예제 (utime.c) 1) 파일의 내용을 truncate 하기 전에 파일의 utime과 atime을 읽음 2) 파일의 내용을 truncate 하면 utime과 atime이 현재 시각으로 변 경됨 3) 저장해둔 utime과 atime으로 복구 4) 파일의 크기는 0으로 변화했지만 utime과 atime은 변화 없음 [실행 결과] % ls -lu afile -rw-r--r-- 1 lsj user 14 Jul 1 09:10 afile % a.out afile % ls -lu afile -rw-r--r-- 1 lsj user 0 Jul 1 09:10 afile 57

122 14. 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 */ } 58

123 DIR 구조체 오픈된 디렉토리를 다루는데 사용되는 구조체 표준 I/O 라이브러리의 FILE 구조체와 비슷한 역할 59

124 opendir(), readdir(): 디렉토리 접근 #include <sys/types.h> #include <dirent.h> DIR *opendir (const char *pathname); struct dirent *readdir(dir *dp); opendir()로 디렉토리 파일을 열고 readdir()로 디렉토리 파일의 내용을 읽는다 리턴 값: 성공하면 구조체 주소, 실패하면 NULL readdir()로 읽을 때마다 디렉토리 파일의 current file offset은 읽 은 구조체 dirent의 크기 만큼 증가한다. 60

125 디렉토리의 항목 읽기 위해서는 해당 디렉토리에 대한 읽기 권한이 있어야 한다 그러나 쓰기권한이 있어도 write 함수로 직접 쓸 수는 없다. mkdir rmdir 를 사용해야함 사용자는 디렉토리에 대해서 쓰기 작업을 직접 수행할 수는 없다. 61

126 rewinddir(), closedir() #include <sys/types.h> #include <dirent.h> void rewinddir (DIR *dp); int closedir (DIR *dp); rewinddir() 디렉토리 파일의 current file offset을 처음으로 옮긴다 closedir() 디렉토리 파일을 닫는다. 리턴 값: 성공하면 0, 실패하며 -1 62

127 mkdir() #include <sys/types.h> #include <sys/stat.h> int mkdir (const char *pathname, mode_t mode ); 새로운 디렉토리를 만든다. 리턴 값: 성공하면 0, 실패하면 -1 성공하면 "." 와 ".." 파일은 자동적으로 만들어진다. "."은 이 디렉토리 파일의 i-node를, ".."은 부모 디렉토리 파일의 i-node를 가르킨다 63

128 rmdir() #include <unistd.h> int rmdir (const char *pathname ); 비어 있는 디렉토리를 삭제한다. 디렉토리 파일의 link count를 감소 시킴 link count가 0이 되면 삭제됨 리턴 값: 성공하면 0, 실패하면 -1 64

129 #include <sys/types.h> /* listfiles.c */ #include <sys/stat.h> #include <dirent.h> #include <stdio.h> #include "error.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('?'); } 65

130 /* 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, " "); /* The permission bits are three sets of three * bits: user read/write/exec, group read/write/exec, * other read/write/exec. We deal with each set * of three bits in one pass through the loop. */ 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++; } /* Put special codes in for set-user-id, set-group-id, * and the sticky bit. (This part is incomplete; "ls" * uses some other letters as well for cases such as * set-user-id bit without execute bit, and so forth.) */ 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); 66

131 /* outputstatinfo - print out the contents of the stat structure. */ void outputstatinfo(char *pathname, char *filename, struct stat *st) { int n; char slink[bufsiz+1]; } /* Print the number of file system blocks, permission bits, * number of links, user-id, and group-id. */ 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 the file is not a device, print its size; otherwise * print its major and minor device numbers. */ 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)); /* Print the access time. The ctime() function is * described in Chapter 7, "Time of Day Operations." */ printf("%.12s ", ctime(&st->st_mtime) + 4); /* Print the file name. If it's a symblic link, also print * what it points to. */ 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); } 67

132 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; /* Open the directory */ if ((dp = opendir(dirname)) == NULL) error(dirname); printf("%s:\n", dirname); /* For each file in the directory... */ while ((d = readdir(dp))!= NULL) { /* Create the full file name. */ sprintf(filename, "%s/%s", dirname, d->d_name); /* Find out about it. */ if (lstat(filename, &st) < 0) error(filename); /* Print out the information. */ outputstatinfo(filename, d->d_name, &st); putchar('\n'); } putchar('\n'); closedir(dp); } return 0; } 68

133 chdir(), fchdir() #include <unistd.h> int chdir (const char *pathname); int fchdir (int filedes); 현재 작업 디렉토리를 변경한다 반환 값: 성공하면 0, 실패하면 -1 현재 작업 디렉토리는 프로세스의 속성 69

134 getcwd() #include <unistd.h> char *getcwd (char *buf, size_t size ); 현재 작업 디렉토리 경로명을 얻는다 리턴 값: 성공하면 buf의 주소, 실패하면 NULL 70

135 #include <unistd.h> #include <stdio.h> #include "error.h" #define PATH_MAX 1024 int main(void) { char path[path_max+1]; if(chdir("/tmp")<0) error("error chdir"); else { if(getcwd(path, PATH_MAX) == NULL) error("error getcwd"); else printf("current working directory changed to %s \n", path); } } 71

136 15. sync(), fsync() #include <unistd.h> void sync (); int fsync(int filedes); 버퍼에 있는 내용을 디스크에 쓰도록 한다. sync()는 시스템 데몬 프로세스에 의해서 30초마다 호출된다. I/O 작업이 끝나기 전에 리턴한다 fsync()는 지정된 파일에 대해서만 I/O 작업을 수행하도록 한다. I/O 작업이 끝난 후 리턴한다 참고) O_SYNC 플래그 72

137 고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 4장. 표준 입출력 라이브러리 (Standard I/O Library)

138 Contents 1. Standard I/O Library 2. Buffing 3. Opening a Stream: fopen() 4. Reading / Writing a Stream 5. Standard I/O Efficiency 6. Binary I/O: fread() 7. Positioning a Stream 8. Formatted I/O 9. Temporary Files 2

139 1. Standard I/O Library Written by Dennis Ritchie in 1975 Implemented on many OS ANSI C Standard Library Buffer allocation 최적의 크기 단위로 I/O를 수행 디스크 I/O 횟수 최소화 Streams 문자의 흐름으로 파일 입출력을 다룬다 3

140 System calls vs. C Library functions application code user process C library functions C library buffers system calls system buffers (buffer caches) kernel hardware (harddisk ) 4

141 FILE 구조체 3장의 파일 관련 시스템 호출 함수 à 파일 디스크립터 (file descriptor) 표준 입출력 함수 à FILE 구조체에 대한 포인터 하나의 스트림을 다루기 위한 정보를 포함하는 구조체 파일 디스크립터 (File descriptor) 버퍼에 대한 포인터, 버퍼 크기 에러 플래그 등 #include <stdio.h> 5

142 FILE 구조체 FILE * (FILE 구조체에 대한 포인터) 스트림을 열면 (fopen 함수) 리턴됨 표준 I/O 함수들의 파라미터로 전달해야함 프로그래머는 FILE 구조체의 내부를 알 필요 없음 6

143 FILE 구조체 typedef struct { int _cnt; unsigned char *_ptr; unsigned char *_base; unsigned char _flag; unsigned char _file; } FILE ; _cnt : 버퍼에 남아 있는 문자의 수 _ptr : 버퍼 내에 다음에 쓸(읽을) 위치를 가리키는 포인터 _base : 버퍼 시작 주소 _flag : 스트림의 현재 상태 _IOFBF, _IOLBF, _IONBUF _IOEOF, _IOERR _IOREAD, _IOWRT _file : 파일 디스크립터 7

144 표준 입력/출력/에러 스트림 (stream) stdin, stdout, stderr FILE* #include <stdio.h> 파일 디스크립터 (file descriptorint) STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO int #include <unistd.h> 8

145 2. Buffing C library buffer 사용 목적 디스크 I/O 수행의 최소화 read (), write () 함수 호출의 최소화 최적의 크기 단위로 I/O 수행 시스템 성능 향상 C library buffer 방식 fully buffered line buffered unbuffered 9

146 C library buffer 방식 Fully Buffered 버퍼가 꽉 찼을 때 실제 I/O 수행 디스크 파일 입출력 Line Buffered 줄 바꿈 문자(newline)에서 실제 I/O 수행 터미널 입출력 (stdin, stdout) Unbuffered 버퍼를 사용하지 않는다. 표준 에러 (stderr) 10

147 setbuf() setvbuf() #include <stdio.h> void setbuf (FILE *fp, char *buf ); int setvbuf (FILE *fp, char *buf, int mode, size_t size ); 버퍼의 관리 방법을 변경한다 호출 시기 스트림이 오픈된 후, 입출력 연산 수행 전에 호출되어야 함 11

148 setbuf() void setbuf (FILE *fp, char *buf ); 버퍼 사용을 on/off 할 수 있다. buf 가 NULL 이면 unbuffered buf 가 BUFSIZ 크기의 공간을 가리키면 fully/line buffered 터미날 장치면 line buffered 그렇지 않으면 fully buffered 12

149 setvbuf() int setvbuf (FILE *fp, char *buf, int mode, size_t size ); 버퍼 사용 방법을 변경 리턴 값: 성공하면 0, 실패하면 nonzero mode _IOFBF : fully buffered _IOLBF : line buffered _IONBF : unbuffered 13

150 setvbuf() mode == _IONBF buf 와 size 는 무시됨 mode == _IOLBF or _IOFBF buf 가 NULL이 아니면 buf 에서 size 만큼의 공간 사용 NULL이면 라이브러리가 알아서 적당한 크기 할당 사용 stat 구조체의 st_blksize 크기 할당 (disk files) st_blksize 값을 알 수 없으면 BUFSIZ 크기 할당 (pipes) 14

151 setvbuf() Function mode buf Buffer & length Type of buffering setbuf nonnull user buf of length BUFSIZ fully or line buffered NULL no buffer unbuffered setvbuf _IOFBF nonnull user buf of length size fully buffered NULL System buffer of appropriate length _IOLBF nonnull user buf of length size line buffered NULL System buffer of appropriate length _IONBF ignored no buffer unbuffered 일반적으로 표준 C 라이브러리가 버퍼의 크기를 결정하고 할당하도록 하는 것이 좋다 15

152 #include <stdio.h> /* buffer.c */ main() { char buf[bufsiz]; } printf("hello, "); sleep(1); printf("unix!"); sleep(1); printf("\n"); sleep(1); setbuf(stdout,null); printf("how "); sleep(1); printf("are "); sleep(1); printf("you?"); sleep(1); printf("\n"); sleep(1); 16

153 fflush() #include <stdio.h> int fflush (FILE *fp); fp 스트림의 출력 버퍼에 남아있는 내용을 write() 시스템 호출을 통 하여 커널에 전달한다 리턴 값 : 성공하면 0, 실패하면 EOF (-1) fp 가 NULL이면, 모든 출력 스트림의 출력 버퍼에 남아있는 내용을 커널에 전달한다 17

154 3. Opening a Stream: fopen() #include <stdio.h> FILE *fopen (const char *pathname, const char *type); 파일을 스트림으로 연다 리턴 값: 성공하면 FILE *, 실패하면 NULL fopen () 함수는, FILE 구조체의 각 필드들을 초기화 한 후에 open() 함수를 호출한다. 18

155 fopen() - type type 파라미터 "r", "rb" "w", "wb" "a", "ab" "r+", "r+b", "rb+" "w+", "w+b", "wb+" "a+", "a+b", "ab+" Description open for reading O_RDONLY truncate to 0 length or create for writing O_WRONLY O_CREAT O_TRUNC append; open for writing at end of file, or create for writing O_WRONLY O_APPEND O_CREAT open for reading and writing O_RDWR truncate to 0 length or create for reading and writing O_RDWR O_CREAT O_TRUNC open or create for reading and writing at end of file O_RDWR O_APPEND O_CREAT 19

156 fopen() - type Restriction r w a r+ w+ a+ file must already exist o o previous contents of file discarded o o stream can be read o o o o stream can be wirtten o o o o o stream can be wirtten only an end o o 20

157 fopen() - "b" "b" 를 지정해주면 binary option, 지정해 주지 않으면 text option FTP 의 binary 명령과 같은 효과 UNIX에서는 à 아무 효과 없음 Windows 운영체제에서 binary option à 아무 효과 없음 Windows 운영체제에서 text option 일 경우 '\n' 을 출력하면 '\r', '\n' 으로 자동 변환됨 '\r', '\n' 을 읽으면 '\n' 으로 자동 변환됨 21

158 제한사항 출력 함수 다음에 입력함수를 호출하기 위해서는, 사이에 fflush(), fseek(), fsetpos(), rewind() 등의 함수를 반드시 호출해야 한다. 입력 함수 다음에 출력함수를 호출하기 위해서는, 사이에 fseek(), fsetpos(), rewind() 등의 함수를 호출하거나 입력 연산이 파일의 끝 에 도달했어야 한다. 파일이 새로 생성될 경우에, 새로 생성하는 파일에 대한 permission S_IRUSR S_IWUSR S_IRGRP S_IWGRP S_IROTH S_IWOTH POSIX.1 표준 22

159 freopen() #include <stdio.h> FILE *freopen (const char *pathname, const char *type, FILE *fp ); fp 가 가리키는 스트림으로 파일을 연다 fp 가 이미 열려진 스트림이면 새로 열기 전에 먼저 닫는다 stdin, stdout, stderr 스트림으로 파일을 열 때 사용한다 리턴 값 : 성공하면 FILE* fp, 실패하면 NULL type : fopen()에서와 같음 23

160 #include <fcntl.h> /* freopen.c */ #include <stdio.h> #include "error.h" main() { FILE* f; } printf("this is displayed on the screen.\n"); if((f = freopen("afile", "w", stdout)) == NULL) error("freopen"); printf("this is written into the redirected file.\n"); 24

161 fdopen() #include <stdio.h> FILE *fdopen (int filedes, const char *type); 이미 열려진 파일 디스트립터 (filedes)에 대해, 표준 입출력의 스트 림을 생성하여 리턴한다 파일 디스트립터 -> FILE * pipe, cummunication channel 등을 열 때 사용 25

162 fclose() #include <stdio.h> int fclose ( FILE *fp ); 스트림을 닫는다 리턴 값: 성공하면 0, 실패하면 EOF (-1) 출력 버퍼에 있는 모든 자료는 파일에 저장되고, 입력 버퍼에 있는 모든 자료는 버려진다. 프로세스가 정상적으로 종료한 경우에는 모든 열려진 스트림이 저절 로 닫힌다 26

163 4. Reading / Writing a Stream 3 types of Unformatted I/O: Character-at-a-time I/O: getc(), fgetc(), getchar() Line-at-a-time I/O: fgets(), fputs() Direct I/O: fread(), fwrite() read/write some number of objects Formatted I/O: scanf(), fscanf(), printf(), fprintf() 27

164 getc() fgetc() getchar() #include <stdio.h> int getc (FILE *fp ); int fgetc (FILE *fp ); int getchar (void ); 스트림에서 한 문자를 읽어온다 Return: next char if OK, EOF on EOF or error 28

165 getc() fgetc() getchar() getc()는 매크로 함수 인자로 side effect 없는 수식을 사용하여야 한다 함수의 주소를 얻을 수 없다 fgetc()는 함수 함수의 주소를 사용할 수 있다 수행 시간은 getc()가 빠르다 getchar()는 getc(stdin)과 같다 29

166 에러검사: ferror() feof() #include <stdio.h> int ferror (FILE *fp); int feof (FILE *fp); void clearerr (FILE *fp); 스트림 입력 함수가 EOF 를 리턴했을 때, feor() : 파일의 끝에 도달했는지 확인 ferror() : 에러가 발생했는지 확인 clearerr()는 EOF 상태나 에러 상태를 지운다 30

167 ungetc() #include <stdio.h> int ungetc (int c, FILE *fp ); 문자를 스트림에 다시 되돌림 리턴 값: 성공하면 c, 실패하면 EOF c 는 원래 읽었던 문자일 필요는 없음 단어나 토큰(token) 단위로 읽을 때 사용 다음 문자가 무엇인지 미리 읽고 난 후 되돌릴 때 31

168 putc() fputc() putchar() #include <stdio.h> int putc (int c, FILE *fp ); int fputc (int c, FILE *fp ); int putchar (int c ); 스트림에 한 문자를 쓴다 Return: c if OK, EOF on error 32

169 putc() fputc() putchar() putc()는 매크로 함수 인자로 side effect 없는 수식을 사용하여야 한다 함수의 주소를 얻을 수 없다 fputc()는 함수 함수의 주소를 사용할 수 있다 수행 시간은 putc()가 빠르다 putchar()는 putc(stdout)과 같다 33

170 fgets() #include <stdio.h> char *fgets (char *buf, int n, FILE *fp ); '\n' 문자까지 한줄을 입력받는다 '\n' 문자도 읽혀지고 '\0' 이 채워진다 n - 1 개 이상의 문자열을 읽을 수는 없다 Return buf if OK, NULL on end of file or error 34

171 gets() #include <stdio.h> char *gets (char *buf ); 표준 입력으로부터 한 줄을 읽어 들인다 '\n' 문자를 buf 에 저장하지 않는다. deprecated function buffer overflow 에러가 발생할 수 있으므로 바람직하지 않다 Return buf if OK, NULL on end of file or error 35

172 fputs() puts() #include <stdio.h> int fputs (const char *str, FILE *fp ); int puts (const char *str); 문자열을 스트림에 출력한다 puts() 는 stdout에 출력하고, '\n'을 덧붙인다 Return nonnegative value if OK, EOF on error 36

173 5. Standard I/O Efficiency How does the three types of unformatted I/O compare in efficiency? How does unformatted I/O compare with direct read() and write()? Are macros more efficient than functions? Why? What about Program Text size? 37

174 #include <stdio.h> /* fputc.c */ #include "error.h" #define FILESIZE (100 * 1024 * 1024) main() { FILE* f; int i, fd; if ((f = fopen("file.write", "w")) == NULL) error("file.write"); for (i=0; i < FILESIZE; ++i) fputc('.', f); } fclose(f); 38

175 Function User CPU (seconds) System CPU (seconds) Clock time (seconds) #loops write() (write2.c) , , ,857,600 User CPU (seconds) System CPU (seconds) Clock time (seconds) #loops Bytes of program text fputc() (fputc.c) putc() (putc.c) ,857, ,857,

176 6. Binary I/O: fread() #include <stdio.h> size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp ); 스트림에서 이진 데이터를 읽는다 size 크기의 객체를 nobj 개 ptr 에 읽어들인다 리턴 값: 읽은 객체의 수 리턴 값이 nobj 값보다 작으면 파일의 끝이거나 에러 ferror(), feof() 40

177 fwrite() #include <stdio.h> size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp ); 스트림에 이진 데이터를 출력한다 size 크기의 객체를 nobj 개 출력한다 리턴 값: 출력된 객체의 수 41

178 Binary Data Exchange May be incompatible among different machine architectures because: Offset of a member in a structure can differ between compilers and systems Binary formats of int and float may differ between different machines (little endian, big endian) So use a higher level protocol instead! 42

179 7. Positioning a Stream #include <stdio.h> long ftell (FILE *fp ); int fseek (FILE *fp, long offset, int whence ); void rewind (FILE *fp); ftell() - 파일의 현재 위치를 리턴, -1 on error fseek() 파일의 현재 위치를 변경 (lseek() 참고) whence : SEEK_SET, SEEK_CUR, SEEK_END Returns: 0 if OK, nonzeron on error rewind() 파일의 현재 위치를 파일 선두로 변경 fseek (fp, 0L, SEEK_SET) 43

180 fgetpos() fsetpos() #include <stdio.h> int fgetpos (FILE *fp, fpos_t *pos ); int fsetpos (FILE *fp, const fpos_t *pos ); 새 ANSI C 표준, fpos_t 형 도입 fgetpos() 파일의 현재 위치를 pos 에 얻는다 fsetpos() 파일의 현재 위치를 pos 로 설정 Return 0 if OK, nonzero on error 44

181 8. Formatted I/O Formatted Output printf() fprintf() sprintf() vprintf() vfprintf() vsprintf() Formatted Input scanf() fscanf() sscanf() 45

182 printf() fprintf() sprintf() #include <stdio.h> int printf (const char *format, ); int fprintf (FILE *fp, const char *format, ); int sprintf (char *buf, const char *format, ); printf() - stdout 에 출력 fprintf() - fp 스트림에 출력 Both return: number of characters output if OK, negative value if output error sprintf() 문자열 buf 에 출력 ('\0' 이 추가됨) Returns: number of characters stored in array 46

183 vprintf() vfprintf() vsprintf() #include <stdarg.h> #include <stdio.h> int vprintf (const char *format, va_list arg ); int vfprintf (FILE *fp, const char *format, va_list arg ); int vsprintf (char *buf,const char *format, va_list arg ); 가변 인자 리스트(variable length argument lists)를 va_list args 로 전달 47

184 scanf() fscanf() sscanf() #include <stdio.h> int scanf (const char *format, ); int fscanf (FILE *fp, const char *format, ); int sscanf (const char *buf,const char *format, ); scanf() 표준 입력에서 입력 fscanf() 스트림 fp 에서 입력 sscanf() 문자열 buf 에서 입력 Return: number of input items assigned, EOF if input error or end of file before any conversion 48

185 9. Temporary Files #include <stdio.h> char *tmpnam(char *ptr); FILE *tmpfile (void ); char *tempnam(const char *directory,const char *prefix ); tmpnam() : 임시파일이름 생성 L_tmpnam : 파일 이름의 최대 길이 상수 (stdio.h> if ptr!= NULL: ptr 에 이름 저장하고 ptr 리턴 if ptr == NULL: 라이브러리 내부 static 변수에 이름 저장하고 주소 리턴 tmpfile() : "wb+" 로 임시파일을 생성하고 스트림 포인터 리턴 tempnam() : 만들어질 임시 파일 이름의 경로와 접두어를 지정 49

186 고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 5장. 고급 입출력 (Advanced I/O)

187 Contents 1. Nonblocking I/O 2. Record Locking 3. I/O Multiplexing 4. Asynchronous I/O 5. Memory Mapped I/O 2

188 1. Nonblocking I/O Blocking I/O I/O 작업이 완료되기를 기다리며 영원히 리턴안할 수 있다 (block forever) 예) getchar() 은 엔터키를 입력할 때까지 영원히 기다린다 Nonblocking I/O I/O 작업이 당장 완료될 수 없으면 곧장 에러를 리턴한다 예) 이미 입력된 키가 있으면 그 값을 리턴하고, 아니면 기다리지 않고 즉시 에러를 리턴한다 주의: Asynchronous I/O 와 혼동하지 말라 3

189 Slow system calls which can block forever Reads from pipes, terminals, network devices, if data isn't present Writes to above if they don't handle reading promptly Opens of files block until some condition occurs Open of a terminal device attached to a modem Open of a FIFO for writing only when there is no other process for reading the FIFO Reads and writes of files that have mandatory record locking enabled Certain ioctl operations Some of IPC functions 4

190 Nonblocking I/O 설정 방법 open() 으로 파일을 열 때 O_NONBLOCK 플래그 open("a.out",o_rdonly O_NONBLOCK); 열려진 파일에 대하여 fcntl() 함수로 O_NONBLOCK 플래그 설정 int flag; flag = fcntl(fd, F_GETFL, 0); flag = O_NONBLOCK; fcntl(fd, F_SETFL, flag); O_NONBLOCK 플래그 설정 취소 int flag; flag = fcntl(fd, F_GETFL, 0); flag &= ~O_NONBLOCK; fcntl(fd, F_SETFL, flag); 5

191 #include <fcntl.h> #include "ourhdr.h" void set_fl(int fd, int flags) { int val; } if ( (val = fcntl(fd, F_GETFL, 0)) < 0) err_sys("fcntl F_GETFL error"); val = flags; /* turn on flags */ if (fcntl(fd, F_SETFL, val) < 0) err_sys("fcntl F_SETFL error"); void clr_fl(int fd, int flags) { int val; } if ( (val = fcntl(fd, F_GETFL, 0)) < 0) err_sys("fcntl F_GETFL error"); val &= ~flags; /* turn flags off */ if (fcntl(fd, F_SETFL, val) < 0) err_sys("fcntl F_SETFL error"); 6

192 #include <sys/types.h> /* nonblockw.c */ #include <errno.h> #include <fcntl.h> #include "ourhdr.h" char buf[100000]; int main(void) { int ntowrite, nwrite; char *ptr; } ntowrite = read(stdin_fileno, buf, sizeof(buf)); fprintf(stderr, "read %d bytes\n", ntowrite); set_fl(stdout_fileno, O_NONBLOCK); /* set nonblocking */ for (ptr = buf; ntowrite > 0; ) { errno = 0; nwrite = write(stdout_fileno, ptr, ntowrite); fprintf(stderr, "nwrite = %d, errno = %d\n", nwrite, errno); if (nwrite > 0) { ptr += nwrite; ntowrite -= nwrite; } } clr_fl(stdout_fileno, O_NONBLOCK); /* clear nonblocking */ exit(0); 7

193 2. Record Locking 하나의 파일에 두 프로세스가 동시에 쓴다면 어떤 내용은 덮어 쓰여 질 수 있다 만약 쓰여지는 내용이 파일의 뒤에 덧붙여지기만 할 것이라면 open() 에서 O_APPEND 모드로 열면 된다 한 프로세스가 파일의 영역을 읽거나 수정할 때 다른 프로세스의 접 근을 제한하기 위해서는 그 영역에 lock 을 걸어야 한다 8

194 Advisory vs. Mandatory Locking Advisory Locking lock 을 걸 수 있고 검사할 수 있지만 강제되지는 않는다 즉 locking 규칙을 무시하고 읽고 쓰기 가능 따라서 모든 프로세스들이 자발적으로 규칙을 준수해야함 Mandatory Locking 커널이 locking 규칙을 강제하므로 무시하고 읽고 쓰기 불가능 커널이 모든 입출력 함수의 호출을 감시해야 하므로 시스템 부하 증가 설정 방법: set-group-id 비트를 켜고 group-execute 비트를 끔 -rw-r-sr-- 1 lsj 5 Jul 15 12:11 lockfile 9

195 Compatibility between different lock types Request for read lock Request for write lock Region currently has No locks OK OK One or more read locks One write lock OK denied denied denied Types of Locks F_RDLCK : Shared Read Lock F_WRLCK : Exclusive Write Lock 10

196 fcntl() #include <sys/types.h> #include <unistd.h> #include <fcntl.h> int fcntl(int filedes, int cmd, struct flock *flockptr); returns : depends on cmd if OK, -1 on error cmd : F_GETLK, F_SETLK, F_SETLKW 11

197 fcntl() F_GETLK flockptr 에 설정한 lock 을 걸 수 있는지, 즉 이미 lock 이 걸려 있는지 검사 걸 수 없다면 이미 걸려있는 lock 정보 flockptr 가 채워짐 걸 수 있다면 flockptr 의 l_type 만 F_UNLCK 으로 변경됨 F_SETLK and l_type == F_RDLCK or F_WRLCK flockptr 에 설정한 lock 을 건다 실패하면 즉시 -1을 리턴한다 (errno = EACCESS or EAGAIN) F_SETKL and l_type == F_UNLCK flockptr 에 설정한 lock 을 해제한다 12

198 fcntl() F_SETLKW F_SETLK 의 blocking version 프로세스는 lock 이 가능할 때까지 sleep 상태가 된다 This sleep is interrupted if a signal is caught 13

199 fcntl() struct flock { short l_type; /* F_RDLCK, F_WRLCK, F_UNLCK */ off_t l_start; /* 로킹 영역의 시작 지점 */ short l_whence; /* SEEK_SET, SEEK_CUR, SEEK_END */ off_t l_len; /* 로킹 영역의 길이 (0이면 파일 끝까지) */ pid_t l_pid; /* 프로세스의 PID */ }; When setting or releasing a lock on a file, the system combines or splits adjacent areas as required. 14

200 Requesting and Releasing A Lock #include <sys/types.h> #include <fcntl.h> int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len) { struct flock lock; lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */ lock.l_start = offset; /* byte offset, relative to l_whence */ lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */ lock.l_len = len; /* #bytes (0 means to EOF) */ } return( fcntl(fd, cmd, &lock) ); 15

201 Requesting and Releasing A Lock #define read_lock(fd, offset, whence, len) \ lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len) #define readw_lock(fd, offset, whence, len) \ lock_reg(fd, F_SETLKW, F_RDLCK, offset, whence, len) #define write_lock(fd, offset, whence, len) \ lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len) #define writew_lock(fd, offset, whence, len) \ lock_reg(fd, F_SETLKW, F_WRLCK, offset, whence, len) #define un_lock(fd, offset, whence, len) \ lock_reg(fd, F_SETLK, F_UNLCK, offset, whence, len) 16

202 Tesing for A Lock #include <sys/types.h> #include <fcntl.h> #include "ourhdr.h" pid_t lock_test(int fd, int type, off_t offset, int whence, off_t len) { struct flock lock; lock.l_type = type; /* F_RDLCK or F_WRLCK */ lock.l_start = offset; /* byte offset, relative to l_whence */ lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */ lock.l_len = len; /* #bytes (0 means to EOF) */ if (fcntl(fd, F_GETLK, &lock) < 0) err_sys("fcntl error"); } if (lock.l_type == F_UNLCK) return(0); /* false, region is not locked by another proc */ return(lock.l_pid); /* true, return pid of lock owner */ 17

203 Implied Inheritance and Release of Locks 프로세스가 종료하면 그 프로세스가 설정한 모든 lock 은 해제된다 file descriptor 가 닫히면 이와 관련된 모든 lock 은 해제된다. 다음과 같은 경우들에도 모든 lock 은 해제된다 fd1 = open("a", ); read_lock(fd1, ); fd2 = dup(fd1); close(fd2) fd1 = open("a", ); read_lock(fd1, ); fd2 = open("a", ); close(fd2) 18

204 Implied Inheritance and Release of Locks fork() 에 의한 자식 프로세스에게 lock 은 상속되지 않는다 exec() 의 경우에는 상속된다 19

205 Kernel Implementation fd1 = open("a", ); write_lock(fd1, 0, ); /* parent write locks byte 0 */ If (fork() > 0) { /* parent */ fd2 = dup(fd1); fd3 = open("a", ); pause(); close(fd3); /* is the write lock released? */ } else { /* child */ read_lock(fd1, ); /* child read locks byte 1 */ pause(); } 위 실행 결과는 다음 슬라이드와 같음 lock 은 file descriptor 가 아니고 file 에 연관되어 있다 따라서 fd1, fd2, fd3 중 어느 것이라도 close 하면 lock 은 해제 된다 20

206 Kernel Implementation process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2:.... file table fd status flags current file offset v-node ptr fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size linked list of locks file descriptors fd 0: fd flags ptr fd 1: fd 2:.... struct flock link flags, etc starting offset length process ID struct flock link flags, etc starting offset length process ID 21

207 Mandatory Locking with read and write Blocking descriptor, tries to Non Blocking descriptor, tries to read write read write Read lock exists on region OK blocks OK EAGAIN Write lock exists on region blocks blocks EAGAIN EAGAIN open() with O_TRUNC or O_CREAT fails with outstanding mandatory locks (either read locks or wirte locks) 22

208 3. I/O Multiplexing What if we have to read from two descriptor? Blocking I/O in a loop? 한 디스크립터에서 읽기 위해 블록되어있는 동안 다른 디스크립터 에서 데이터를 읽을 수 없다 다른 기법이 필요 23

209 Read from two descriptor Nonblocking I/O using polling 첫번째 디스크립터에서 읽는다 데이터가 있으면 읽어서 처리하고 없으면 리턴하여 두번째 디스크팁터에서 읽는다 데이터가 있으면 읽어서 처리하고 없으면 리턴하여 일정 시간 동안 대기하고 (sleep) 다시 첫번째 디스크립터에서 읽는 것부터 반복한다 문제점 일종의 polling 불필요한 반복으로 CPU 시간의 낭비 24

210 Read from two descriptor Asynchronous I/O 어느 디스크립터에서 읽을 데이터가 있을 때 커널이 이를 signal 로 통보해 주도록 한다 불필요한 polling 을 피할 수 있다 문제점 표준화된 방법이 없음 읽어야할 디스크립터가 무엇인지 알 수 없음 25

211 Read from two descriptor I/O multiplexing 디스크립터들을 파라미터로 I/O multiplexing 함수를 호출한다 디스크립터들 중 하나에서 읽을 수 있을 때까지 대기한다 CPU 시간을 낭비하지 않는다 리턴할 때는 어느 디스크립터에서 읽어야할지 알 수 있다 26

212 select() The arguments we pass to select tell the kernel Which descriptors we're interested in What conditions we're interested in for each descriptor (read, write, exception condition). How long we want to wait. On the return from select, the kernel tells us The total count of the number of descriptors that are ready. Which descriptors are ready for each of the three conditions (read, write, or exception condition). 27

213 select() #include <sys/types.h> #include <sys/time.h> #include <unistd.h> int select(int maxfdp1, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *tvptr); Returns : count of ready descriptors, 0 on timeout, -1 on error maxfdp1 : max fd plus 1 readfds,writefds, exceptfds : pointers to descriptor sets tvptr : a pointer to a timeval 28

214 select() struct timeval { long tv_sec; /* second */ long tv_usec; /* microseconds */ } the last argument struct timeval *tvptr tvptr == NULL tvptr->tv_sec == 0 && tvptr->tv_usec == 0 tvptr->tv_sec!= 0 tvptr->tv_usec!= 0 29

215 select() tvptr == NULL Wait forever Returns if one of the descriptors is ready or a signal is caught (returns 1 with errno = EINTR) tvptr->tv_sec == 0 && tvptr->tv_usec == 0 Don't wait at all. All descriptors are tested and return is made immediately. tvptr->tv_sec!= 0 tvptr->tv_usec!= 0 Wait for the specified number of seconds and microseconds. Returns if one of descriptor is ready Returns if the timeout expires 30

216 select() The middle three arguments fd_set *readfds fd_set *writefds fd_set *exceptfds fd_set: 파일 디스크립터의 set Specify which descriptors we're interested in and for which conditions(readable, writable, or an exception condition) Any of the middle three arguments can be null pointers If all three pointers are NULL, then select can be used a higher precision timer than sleep 31

217 select() readfds writefds exceptfds fd0 fd1 fd one bit per possible descriptor fd_set data type FD_ZERO(fd_set *fdset); // clear all bits in fdset FD_SET(int fd, fd_set *fdset); // turn on bit for fd in fdset FD_CLR(int fd, fd_set *fdset); // turn off bit for fd in fdset FD_ISSET(int fd, fd_set *fdset); // test bit for fd in fdset 32

218 select() The first argument, maxfdp1 max fd plus 1 the highest descriptor set, add 1 최대값: FD_SETSIZE in <sys/types.h> 33

219 select() - three possible return values -1 : error occurred A signal is caught before any of descriptor is ready 0 : no descriptors are ready The time limit expires before any of the descriptors are ready the number of descriptors that are ready Only the ready descriptors are set in the three descriptors returned 34

220 select() what 'ready' means A descriptor in the read set (readfds) is considered ready if a read from that descriptor won't block A descriptor in the write set (writefds) is considered ready if a write from that descriptor won't block A descriptor in the exception set is considered ready if there is an exception condition pending on that descriptors the arrival of out-of-band data on a network connnection certain conditions occurring on a pseudo terminal that has been placed into packet mode 35

221 select() Whether a descriptor is blocking or not doesn't affect where select blocks or not The end of file is read condition, not exception condition 36

222 select() 사용예 fd_set readset, writeset; FD_ZERO(&readset); FD_ZERO(&writeset); FD_SET(0, &readset); FD_SET(3, &readset); FD_SET(1, &writeset); FD_SET(2, &writeset); if ((n = select(4, &readset, &writeset, NULL, NULL)) > 0) { if (FD_ISSET(0, &readset)) if (FD_ISSET(3, &readset)) if (FD_ISSET(1, &writeset)) if (FD_ISSET(2, &writeset)) } 37

223 4. Asynchronous I/O 입출력 가능시 시그널 발생 BSD 계열: SIGIO,SIGURG, SysV 계열: SIGPOLL 입출력 시그널은 하나뿐이므로 두 개 이상의 디스크립터를 다중화할 때는 앞서 설명한 다중화 모델 필요 38

224 readv() writev() #include <sys/types.h> #include <sys/uio.h> int readv(int filedes, const struct iovec iov[], int iovcnt); int writev(int filedes, const struct iovec iov[], int iovcnt); Both return: number of bytes read or written, -1 on error Read into and write from multiple noncontiguous buffers in a single function call called scatter read and gather write fd : file descriptor iov[] : buffers 39

225 struct iovec struct iovec { void *iov_base; /* 버퍼 시작 주소 */ size_t iov_len; /* 버퍼 크기 */ }; iov[0].iov_base iov[0].iov_len iov[1].iov_base iov[1].iov_len iov[iovcnt-1].iov_base iov[iovcnt-1].iov_len len0 len1 lenn buffer0 len0 buffer1 len1 bufferi leni 40

226 5. Memory Mapped I/O 디스크의 파일에 메모리 주소를 부여한다 주소에서 읽는 것은 파일의 데이터를 읽는다 주소에 쓰면 파일에 저장된다 메모리인 것처럼 포인터와 배열을 사용하여 파일의 데이터를 다룰 수 있게된다 성능 향상을 기대할 수 있다 파일 I/O 에서처럼 시스템 버퍼와 라이브러리 버퍼 사이에 데이터 가 복사될 필요 없다 알고리즘 단순화 마치 메모리처럼 배열과 포인터 사용 가능 41

227 mmap() #include <sys/types.h> #include <sys/mman.h> caddr_t mmap(caddr_t addr, size_t len, int prot, int flag, int filedes, off_t off); Returns : starting address of mapped region if OK, -1 on error 디스크 파일에 메모리 주소를 부여한다 addr : 부여될 메모리 시작 주소 addr 가 NULL 이먄 시스템이 적당한 시작 주소를 선택한다 virtual memory page 의 배수이어야 한다 len : 메모리 크기 42

228 mmap() prot : specify the protection of the mapped region. PROT_READ : the region can be read. PROT_WRITE : the region can be written. PROT_EXEC : the region can be executed. PROT_NONE : the region cannot be accessed (not in 4.3+BSD). The protection specified for a region has to match the open mode of the file. 43

229 mmap() flag : various attributes of the mapped region MAP_FIXED the return value must equal addr MAP_FIXED 가 지정되지 않으면, and addr is nonzero, then the kernel uses addr as a hint. MAP_SHARED 부여된 주소에 쓰면 파일에 저장된다 MAP_SHARED 나 MAP_PRIVATE 중의 하나가 반드시 지정되어야 한다 MAP_PRIVATE 부여된 주소에 쓰면 파일의 복사본이 만들어지고 이후부터는 복사본을 읽고 쓰게 된다 44

230 Example of a memory mapped file high address stack len memory mapped portion of file start addr heap uninitialized data (bss) initialized data low address text file : memory mapped portion of file off len 45

231 #include <sys/types.h> /* mcopy.c */ #include <sys/stat.h> #include <sys/mman.h> /* mmap() */ #include <fcntl.h> #include "ourhdr.h" int main(int argc, char *argv[]) { int fdin, fdout; char *src, *dst; struct stat statbuf; } if (argc!= 3) err_quit("usage: a.out <fromfile> <tofile>"); if ( (fdin = open(argv[1], O_RDONLY)) < 0) err_sys("can't open %s for reading", argv[1]); if ( (fdout = open(argv[2], O_RDWR O_CREAT O_TRUNC, FILE_MODE)) < 0) err_sys("can't creat %s for writing", argv[1]); if (fstat(fdin, &statbuf) < 0) /* need size of input file */ err_sys("fstat error"); if (lseek(fdout, statbuf.st_size - 1, SEEK_SET) == -1) /* set size of output file */ err_sys("lseek error"); if (write(fdout, "", 1)!= 1) err_sys("write error"); if ( (src = mmap(0, statbuf.st_size, PROT_READ, MAP_FILE MAP_SHARED, fdin, 0)) == (caddr_t) -1) err_sys("mmap error for input"); if ( (dst = mmap(0, statbuf.st_size, PROT_READ PROT_WRITE, MAP_FILE MAP_SHARED, fdout, 0)) == (caddr_t) -1) err_sys("mmap error for output"); memcpy(dst, src, statbuf.st_size); /* does the file copy */ exit(0); 46

232 고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 6장. 프로세스 (Process)

233 Contents 1. Process Start 2. Process Termination 3. Command-Line Arguments 4. Environment Variables 5. Memory Layout of a C program 6. Memory Allocation 7. setjmp() longjmp() 2

234 1. Process Start Kernel exec system call user process C start-up routine call return int main(int argc, char * argv[]); 3

235 main() int main(int argc, char *argv[]); arc : the number of command-line arguments argv[] : an array of pointers to the arguments C start-up routine Started by the kernel (by the exec system call) Take the command-line arguments and the environment from the kernel Call main exit( main( argc, argv) ); 4

236 2. Process Termination Normal termination: return from main() calling exit() : calling _exit() Abnormal termination calling abort() terminated by a signal 5

237 exit() #include <stdlib.h> void exit(int status); 프로세스를 정상적으로 종료한다 cleanup processing 을 수행한다 모든 열려진 스트림을 닫고 출력 버퍼의 내용을 디스크에 쓴다 status the exit status of a process 이 값은 UNIX shell 에 의해서 사용됨 6

238 _exit() #include <unistd.h> void _exit(int status); 프로세스를 정상적으로 종료한다 커널로 즉시 리턴한다 7

239 atexit() #include <stdlib.h> void atexit(void (*func)(void)); returns: 0 if OK, nonzero on error exit handler 를 등록한다 프로세스당 32개까지 func an exit handler a function pointer exit() 는 exit handler 들을 등록된 역순으로 호출한다 8

240 C Program Start and Termination _exec user function exit handler _exec call return main function exit (does not return) exit function exit handler user process call return C start-up routine _exit standard I/O cleanup exec kernel 9

241 Example of exit handlers #include "ourhdr.h" /* doatexit.c */ static void my_exit1(void), my_exit2(void); int main(void) { if (atexit(my_exit2)!= 0) err_sys("can't register my_exit2"); if (atexit(my_exit1)!= 0) err_sys("can't register my_exit1"); if (atexit(my_exit1)!= 0) err_sys("can't register my_exit1"); printf("main is done\n"); return 0; } static void my_exit1(void) { printf("first exit handler\n"); } static void my_exit2(void) { printf("second exit handler\n"); } 10

242 3. Command-Line Arguments exec() can pass command-line arguments to a new program Part of normal operation of Unix shells argv[argc] is NULL (ANSI, POSIX.1) 11

243 Echo all command-line arguments #include "ourhdr.h" /* echoarg.c */ int main(int argc, char *argv[]) { int i; } for (i = 0; i < argc; i++) /* echo all command-line args */ printf("argv[%d]: %s\n", i, argv[i]); exit(0); #include "ourhdr.h" /* echoarg1.c */ int main(int argc, char *argv[]) { int i = 0; char **p = argv; } while (*p) printf("argv[%d]: %s\n", i++, *p++); exit(0); 12

244 4. Environment Variables 환경 변수(environment variable)는 부모 프로세스에서 자식 프로세 스로 전달된다.login 또는.cshrc 파일에서 환경 변수를 설정한다. 환경변수: 이름=값 $ env USER=lsj LOGNAME=lsj HOME=/user1/lsj PATH=/bin:/usr/bin:/usr/local/bin:/usr/ccs/bin:/usr/ucb:/usr/openwin/bin:/etc:. MAIL=/var/mail/lsj SHELL=/bin/csh 13

245 Environment List 전역 변수 environ을 이용하여 환경 변수에 접근한다. extern char ** environ; 각 항목은 "환경 변수 이름=값" 의 형식 각 문자열은 '\0'로 끝난다 환경 변수 리스트의 마지막은 NULL 포인터 argv 와 같은 구조 14

246 Environment List environ: environment pointer environment list environment strings "USER=lsj" "LOGNAME=lsj" "HOME=/user1/lsj" "PATH=/bin:/usr/local " "MAIL =/var/mail/lsj"... NULL "SHELL=/bin/csh" 15

247 getenv() #include <stdlib.h> char *getenv(const char *name); Returns : pointer to value associated with name, NULL if not found 환경 변수 리스트에서 이름이 name 인 것을 찾아 값에 대한 포인터를 리턴한다 실패하면 NULL 포인터를 리턴 16

248 putenv() #include <stdlib.h> int putenv(const char *str); Returns: 0 if OK, nonzero on error 환경 변수를 추가한다 str은 "name=value" 형식의 문자열 성공적으로 실행된 경우 0을 리턴 같은 이름의 환경 변수가 이미 있다면 새 값으로 변경된다 17

249 setenv() unsetenv() #include <stdlib.h> int setenv(const char *name, const char *value, int rewrite); Returns: 0 if OK, nonzero on error void unsetenv(const char *name); setenv 는 환경 변수 name = value 을 등록한다 name 의 환경변수가 이미 있을 경우 rewrite!= 0 이면 새 값으로 변경되고 rewrite == 0 이면 값이 변경되지 않는다 unsetenv 는 환경 변수 name 을 제거한다 18

250 5. Memory Latout of a C program high address stack command-line arguments and environment variables low address heap uninitialized data (bss) initialized data text initialized to zero by exec read from program file by exec 19

251 Memory Layout of a C program Text segment: Machine instructions (read-only, sharable) Initialized data segment: e.g. int maxcount = 99; (initialized) Uninitialized data segment: (bss: block started by symbol) e.g. long sum[1000]; Stack: automatic variables, temporary variables, return address, caller's environment (registers) Heap: dynamic memory allocation 20

252 Shared Libraries Static linking library 사용된 라이브러리 루틴들이(예: printf) 실행파일에 추가된다 실행파일 크기 증가 Shared library 실행파일에 라이브러리 루틴들을 포함하지 않는다. 공용의 메모리에 라이브러리 루틴을 로드하고 이를 공유한다 프로그램 크기 감소 처음 실행될때 오버헤드 발생 라이브러리가 버전업되어도 실행파일을 다시 컴파일 않해도됨 21

253 6. Memory Allocation #include <stdlib.h> void *malloc(size_t size); void *calloc(size_t nobj, size_t size); void *realloc(void *ptr, size_t newsize); returns : nonnull pointer if OK, NULL on error void free(void *ptr); dynamic allocation of memory from heap provide suitable alignment ex) doubles must start at the addresses that are multiples of 8 library manages memory pool 22

254 malloc(): allocates specified number of bytes, initial value of memory is indeterminate calloc(): allocates specified number of objects of specified size, initialized to all 0 bits realloc(): changes size of previously allocated memory, initial value of new area is indeterminate 23

255 7. setjmp(), longjmp() #include <setjmp.h> int setjmp(jmp_buf env); returns : 0 if called directly, nonzero if returning from a call to longjmp void longjmp(jmp_buf env,int val); Jump across function call (nonlocal goto) Useful for dealing with error conditions in deeply nested function calls An error occurs, We want to print an error, ignore rest of input, and return to main() Large number of levels à handle return at each level for each error Direct nonlocal goto: setjmp, longjmp 24

256 setjmp store information for return to setjmp point at env returns 0 if called directly returns nonzero(val) if returning from a call to longjmp longjmp use env to jump to setjmp point and val as a return value. Several longjmp can use the same setjmp location with different val. normally env is a global variable since it can be referenced from another function. 25

257 Automatic, Register, Volatile Variables Problems with automatic variables and register variables when using setjmp and longjmp After longjmp,the values of these variables are implementation dependent. A variable stored in a register can be rolled back (returned to the original value saved by setjmp) A volatile variable can not be rolled back. Volatile variables : forces compiler to suppress optimizations. Global and static variables are left alone. 26

258 #include <setjmp.h> /* testjmp.c */ #include "ourhdr.h" static void f1(int, int, int); static void f2(void); static jmp_buf jmpbuffer; int main(void) { int count; register int val; volatile int sum; } count = 2; val = 3; sum = 4; if (setjmp(jmpbuffer)!= 0) { printf("after longjmp: count = %d, val = %d, sum = %d\n", count, val, sum); exit(0); } count = 97; val = 98; sum = 99; /* changed after setjmp, before longjmp */ f1(count, val, sum); /* never returns */ static void f1(int i, int j, int k) { printf("in f1(): count = %d, val = %d, sum = %d\n", i, j, k); f2(); } static void f2(void) { longjmp(jmpbuffer, 1); } 27

259 Results: testjmp.c $ cc testjmp.c $ a.out in f1(): count = 97, val = 98, sum = 99 after longjmp: count = 97, val = 98, sum = 99 $ cc O testjmp.c $ a.out in f1(): count = 97, val = 98, sum = 99 after longjmp: count=2, val=3, sum=99 28

260 고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 7장. 프로세스 통제 (Process Control)

261 Contents 1. Process Identifiers 2. fork() 3. vfork() 4. exit() 5. wait() waitpid() 6. Race Conditions 7. exec 8. Changing User IDs and Group IDs 9. system() 10. Process Times 2

262 1. Process Identifiers Every process has a unique process ID, a nonnegative integer the tmpnam() uses the process ID to generate unique names Process ID 0 : swapper (scheduler process) system process part of the kernel no program on disk corresponds to this process 3

263 Process Identifiers Process ID 1: init process invoked by the kernel at the end of the bootstrap procedure /etc/init or /sbin/init reads the system-dependent initialization files (/etc/rc*) brings the system to a certain state (multi-user) a normal user process but runs with super-user privileges PID 1 is immortal Process ID 2: pagedaemon supports the paging of the virtual memory system kernel process 4

264 Process Identifiers #include <sys/types.h> #include <unistd.h> pid_t getpid(void); pid_t getppid(void); uid_t getuid(void); uid_t geteuid(void); gid_t getgid(void); gid_t getegid(void); // returns process ID // returns parent process ID // returns real user ID // returns effective user ID // returns real group ID // returns effective group ID none of these functions has an error return 5

265 2. fork() #include <sys/types.h> #include <unistd.h> pid_t fork(void); Returns: 0 in child, process ID of child in parent, -1 on error fork() is the ONLY way to create a process in Unix kernel child process is the new process created by fork() fork() is called once, but returns twice! returns 0 in child process returns the child process ID in parent process 6

266 fork() the child process can call getppid() to obtain the parent process ID Parent and child continue executing instructions following the fork() call Child gets a copy of parent s data space, heap, and stack Often, read-only text segment is shared Often, fork() is followed by exec() 7

267 #include <sys/types.h> /* fork1.c */ #include "ourhdr.h" int glob = 6; /* external variable in initialized data */ char buf[] = "a write to stdout\n"; int main(void) { int var; /* automatic variable on the stack */ pid_t pid; var = 88; if (write(stdout_fileno, buf, sizeof(buf)-1)!= sizeof(buf)-1) err_sys("write error"); printf("before fork\n"); /* we don't flush stdout */ } if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) { /* child */ glob++; /* modify variables */ var++; } else sleep(2); /* parent */ printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var); exit(0); 8

268 fork1.c: results $ a.out a write to stdout before fork pid = 430, glob = 7, var = 89 pid = 429, glob = 6, var = 88 $ a.out > temp.out $ cat temp.out a write to stdout before fork pid = 432, glob = 7, var = 89 before fork pid = 431, glob = 6, var = 88 "before fork" printed twice. the standard I/O buffer is copied to the child process and is not yet flushed because it is fully buffered (redirected) in the second execution example 9

269 File sharing after fork() Parent and child share the same file descriptors As if dup() had been called on all open file descriptors Parent and child share the same file offset, o/w overwrite Intermixed output from parent and child 10

270 Handle descriptors after fork() What happens if both parent and child write to the same file opened before fork()? Parent waits for child to complete File offsets updated by child Parent and child go their own way Each closes the descriptors that it doesn t need Often the case with network servers 11

271 File Sharing after fork() parent process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2:.... child process table entry file descriptors fd 0: fd flags ptr fd 1: fd 2:.... file table fd status flags current file offset v-node ptr fd status flags current file offset v-node ptr fd status flags current file offset v-node ptr v-node table v-node information i-node information current file size v-node information i-node information current file size v-node information i-node information current file size 12

272 Properties inherited to the child real user and group ID, effective user and group ID supplementary group IDs process group ID, session ID, set-user-id and set-group ID flags current working directory root directory file mode creation mask signal mask and dispositions the close-on-exec flag for any open file descriptors environment attached shared memory segments resource limits 13

273 Properties not inherited to the child the return value from fork() the process IDs are different file locks pending alarms are cleared for the child the set of pending signals for the child is set to the empty set 14

274 3. vfork() Creates a new process only to exec a new program No copy of parent's address space for child (not needed!) Before exec, child runs in "address space of parent" Efficient in paged virtual memory Child runs first Parent waits until child exec or exit Then the parent resume The deadlock possibility if the child wait for something from the parent 15

275 #include <sys/types.h> /* vfork1.c */ #include "ourhdr.h" int glob = 6; /* external variable in initialized data */ int main(void) { int var; /* automatic variable on the stack */ pid_t pid; var = 88; printf("before vfork\n"); /* we don't flush stdio */ if ( (pid = vfork()) < 0) err_sys("vfork error"); else if (pid == 0) { /* child */ glob++; /* modify parent's variables */ var++; _exit(0); /* child terminates */ } } /* parent */ printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var); exit(0); 16

276 vfork1.c: Results increments by child appear in parent address space $ a.out before vfork pid = 607, glob = 7, var = 89 Instead of _exit() à exit(), results in: $ a.out before vfork ß stdio closed by child 17

277 4. exit() Process Termination A process can terminate in 5 ways: Normal Termination return from main() exit() _exit() Abnormal Termination calling abort() (generates SIGABRT signal) process receives signals 18

278 exit() Process Termination Regardless how a process terminates, the same code in the kernel is eventually executed it closes all the open descriptors for the process, release memory, and so on. 19

279 exit() Termination status Exit status: argument of exit(), _exit() the return value from main() Termination status: Normal termination: Exit status à Termination status Abnormal termination: kernel indicates reason à Termination status 20

280 exit() Termination status Parent can obtain the termination status of the child process by wait() or waitpid() What if parent terminates before child? init becomes the parent of the child process. 21

281 exit() Child Termination Suppose child terminates first If child disappeared, parent would not be able to check child s termination status Zombie: minimal info of dead child process (pid, termination status, CPU time) kept by the kernel for the parent to call wait() or waitpid() init s inherited child do not become zombies init call wait() to fetch status 22

282 5. wait() waitpid() Child terminates Kernel sends SIGCHLD signal to parent an asynchronous event Default action for SIGCHLD signal: ignore it Signal handlers can be defined by users call wait() to fetch the termination status of child 23

283 wait() waitpid() #include <sys/types.h> #include <sys/wait.h> pid_t wait(int *statloc); pid_t waitpid(pid_t pid, int *statloc, int options); Both returns: process ID if OK, 0, or -1 on error A process that calls wait or waitpid can block (if all of its children are still running), or return immediately with the termination status of a child, or return immediately with an error (if it doesn t have any child processes) statloc a pointer to an integer to store the termination status 24

284 Macros to examine the termination status Macro WIFEXITED(status) Description True if child is terminated normally WEXITSATUS(status) : get exit status (low-order 8 bits) WIFSIGNALED(status) WIFSTOPPED(status) True if child is terminated abnormally (by receipt of a signal) WTERMSIG(status) : fetch the signal number that caused the termination. WCOREDUMP(status) : true if a core file was generated True if child is currently stopped WSTOPSIG(status) : fetch the signal number that caused the stop 25

285 #include <sys/types.h> /* prexit.c */ #include <sys/wait.h> #include "ourhdr.h" void pr_exit(int status) { if (WIFEXITED(status)) printf("normal termination, exit status = %d\n", WEXITSTATUS(status)); else if (WIFSIGNALED(status)) printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status), #ifdef WCOREDUMP WCOREDUMP(status)? " (core file generated)" : ""); #else ""); #endif else if (WIFSTOPPED(status)) printf("child stopped, signal number = %d\n", WSTOPSIG(status)); } 26

286 #include <sys/types.h> /* wait1.c */ #include <sys/wait.h> #include "ourhdr.h" int main(void) { pid_t pid; int status; if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) exit(7); /* child */ if (wait(&status)!= pid) err_sys("wait error"); /* wait for child */ pr_exit(status); /* and print its status */ if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) /* child */ abort(); /* generates SIGABRT */ if (wait(&status)!= pid) err_sys("wait error"); /* wait for child */ pr_exit(status); /* and print its status */ if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) /* child */ status /= 0; /* divide by 0 generates SIGFPE */ } if (wait(&status)!= pid) err_sys("wait error"); /* wait for child */ pr_exit(status); /* and print its status */ exit(0); 27

287 wait1.c: Results $ a.out normal termination, exit status = 7 abnormal termination, signal number = 6 (core file generated) abnormal termination, signal number = 8 (core file generated) signal number = 6 ß SIGABRT signal number = 8 ß SIGFPE 28

288 waitpid() waitpid() waits for one particular process provides a nonblocking version of wait supports job control (with the WUNTRACED option) the pid argument for waitpid -1 : waits for any child process > 0 : waits for the child process whose process ID equals pid. 0 : waits for any child whose process GID equals that of the calling process. < -1 : waits for any child whose process GID equals the absolute value of pid. 29

289 waitpid() the options constants for waitpid WNOHANG : does not block if a child specified by pid is not immediately available, return 0 WUNTRACED: job control support returns the status of any stopped child specified by pid if its status has not reported yet WIFSTOPPED macro needs this option 30

290 Avoiding zombie processes A process forks a child It does not wait for the child to complete It does not want child to become zombie How to do this? Answer: fork twice! fork2.c 31

291 #include <sys/types.h> /* fork2.c */ #include <sys/wait.h> #include "ourhdr.h" int main(void) { pid_t pid; if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) { /* first child */ if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid > 0) exit(0); /* parent from second fork == first child */ /* We're the second child; our parent becomes init as soon as our real parent calls exit() in the statement above. Here's where we'd continue executing, knowing that when we're done, init will reap our status. */ sleep(2); printf("second child, parent pid = %d\n", getppid()); exit(0); } if (waitpid(pid, NULL, 0)!= pid) /* wait for first child */ err_sys("waitpid error"); } /* We're the parent (the original process); we continue executing, knowing that we're not the parent of the second child. */ exit(0); 32

292 wait3() wait4() #include <sys/types.h> #include <sys/wait.h> #include <sys/time.h> #include <sys/resource.h> pid_t wait3(int *statloc, int options, struct rusage *rusage); pid_t wait4(pid_t pid, int *statloc, int options, struct rusage *rusage); Both returns: process ID if OK, 0, or -1 on error return the resource information - refer to getrusage() 33

293 wait arguments support Function pid options rusage POSIX.1 SVR4 4.3+BSD wait o o o waitpid o o o o o wait3 o o o o wait4 o o o o 34

294 6. Race Conditions Multiple processes share some data Outcome depends on the order of their execution (i.e. RACE) After fork(), we cannot predict if the parent or the child runs first! The order of execution depends on: system load kernel s scheduling algorithm 35

295 Race Conditions Race condition problems are hard to detect because they work "most of the time"! For parent to wait for child call wait, waitpid, wait3, wait4 For child to wait for parent while (getppid()!= 1) sleep(1); polling! wastes CPU time use signals or other IPC methods 36

296 Race Conditions After fork parent and child both need to do something on its own e.g. parent: write a record in a log file e.g. child: creates a log file Parent and child need to: TELL each other when its initial set of operations are done, and WAIT for each other to complete 37

297 TELL and WAIT child parent #include ourhdr.h TELL_WAIT(); /* setup for TELL_XXX and WAIT_XXX */ if ( (pid = fork()) < 0 ) err_sys( fork error ); else if (pid==0) { /* child */ /* child does whatever is necessary */ TELL_PARENT(getppid()); /* tell parent we're done */ WAIT_PARENT(); /* & wait for parent */ /* and child continues on its way */ exit(0); } /* parent does whatever is necessary */ TELL_CHILD(pid); /*tell child we're done */ WAIT_CHILD(); /* wait for child */ /* and parent continues on its way */ exit(0); 38

298 Race Condition #include <sys/types.h> /* tellwait1.c */ #include "ourhdr.h" static void charatatime(char *); int main(void) { pid_t pid; } if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) charatatime("output from child\n"); else charatatime("output from parent\n"); exit(0); static void charatatime(char *str) { char *ptr; int c; } setbuf(stdout, NULL); /* set unbuffered */ for (ptr = str; c = *ptr++; ) putc(c, stdout); 39

299 tellwait1.c: Results $ a.out output from child output from parent $ a.out oouuttppuutt ffrroomm pcahrielndt $ a.out ooutput from parent utput from child 40

300 Avoid Race Condition #include <sys/types.h> /* tellwait2.c */ #include "ourhdr.h" static void charatatime(char *); int main(void) { pid_t pid; TELL_WAIT(); } if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) { WAIT_PARENT(); /* parent goes first */ charatatime("output from child\n"); } else { charatatime("output from parent\n"); TELL_CHILD(pid); } exit(0); 41

301 7. exec - Program Execution When a process calls one of the exec functions that process is completely replaced by the new program (text, data, heap, and stack segments) and the new program starts at its main function #include <unistd.h> /* exec_echo.c */ int main() { execl("/bin/echo", "echo", "execute /bin/echo", (char*) 0); printf("can this message be printed? ERROR!\n"); } $ a.out execute /bin/echo 42

302 exec functions #include <unistd.h> int execl(const char *pathname, const char *arg0, /* (char*) 0 */); int execv(const char *pathname, const char *argv[]); int execle(const char *pathname, const char *arg0, /* (char*) 0, char *const envp[] */); int execve(const char *pathname, const char *argv[],char *const envp[]); int execlp(const char *filename, const char *arg0, /* (char*) 0 */); int execvp(const char *filename, const char *argv[]); All six return: -1 on error, no return on success 43

303 exec functions postfix (p, l, v, e) p: filename + PATH environment variable l : takes a list of arguments the last argument should be a null pointer v: takes argv[] vector e: takes envp[] array without 'e', the environment variables of the calling process are copied 44

304 Properties inherited to the new program process ID, parent process ID, real user ID, real group ID, supplementary group IDs, process group ID, session ID Controlling terminal time left until alarm clock current working directory root directory file mode creation mask file locks process signal mask pending signals resource limits tms_utime, tms_stime, tms_cutime, tms_ustime values 45

305 Changes on exec FD_CLOEXEC flag for files set à close file descriptors on exec unset (default) à open across exec FD_CLOEXEC flag for directories closed across exec (POSIX.1) UIDs and GIDs real à same across exec effective à may change (sticky bit) 46

306 #include <sys/types.h> /* exec1.c */ #include <sys/wait.h> #include "ourhdr.h" char *env_init[] = { "USER=unknown", "PATH=/tmp", NULL }; int main(void) { pid_t pid; } if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) { /* specify pathname, specify environment */ if (execle("/home/stevens/bin/echoall", "echoall", "myarg1", "MY ARG2", (char *) 0, env_init) < 0) err_sys("execle error"); } if (waitpid(pid, NULL, 0) < 0) err_sys("wait error"); if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid == 0) { /* specify filename, inherit environment */ if (execlp("echoall", "echoall", "only 1 arg", (char *) 0) < 0) err_sys("execlp error"); } exit(0); 47

307 #include "ourhdr.h" /* echoall.c */ int main(int argc, char *argv[]) { int i; char **ptr; extern char **environ; for (i = 0; i < argc; i++) /* echo all command-line args */ printf("argv[%d]: %s\n", i, argv[i]); for (ptr = environ; *ptr!= 0; ptr++) /* and all env strings */ printf("%s\n", *ptr); } exit(0); 48

308 exec1.c: Results $a.out argv[0]: echoall argv[1]: myarg1 argv[2]: MY ARG2 USER=unknown PATH=/tmp argv[0]: echoall $ argv[1]: only 1 arg ß $ prompt, the parent process finished USER=stevens HOME=/home/stevens... EDITOR=/usr/ucb/vi 49

309 8. Changing User IDs and Group IDs #include <sys/types.h> #include <unistd.h> int setuid(uid_t uid); int setgid(gid_t gid); Both return: 0 if OK, -1 on error setuid() sets the real/effective user ID If the process has superuser privileges, it sets the real user ID, effective user ID, saved set-user-id to uid else if uid equals either the real user ID or the saved set-user-id, it sets effective user ID (Others do not change.) to uid else errno is set to EPERM, returns -1. setgid() sets the real/effective group ID 50

310 Changing User IDs and Group IDs Only a superuser process can change the real user ID login(1) calls setuid to set all three user IDs The effective user ID is set from the file s user ID by the exec functions, only if the set-user-id bit is set for the program file. The saved set-user-id is copied from the effective user ID by exec after the effective user ID is stored from the file s user ID (if set-user-id on) 51

311 Different ways to change the three User IDs ID exec setuid(uid) set-user-id bit off set-user-id bit on superuser unprivileged user real user ID unchanged unchanged set to uid unchanged effective user ID unchanged set from user ID of program file set to uid set to uid saved set-user ID copied from effective user ID copied from effective user ID set to uid unchanged 52

312 What is "saved set-uid"? Example: Berkeley tip program Program to remote connection through modem exclusive access through lock files 1. tip is owned by uucp, set-uid bit is SET, on exec: Real UID = our own UID Effective UID = uucp Saved set-uid = uucp 2. tip can accesses lock files owned by uucp allowed because e-uid == uucp 53

313 What is "saved set-uid"? 3. tip executes setuid(getuid()) Real UID = our own UID (unchanged!) Effective UID = our own UID Saved set-uid = uucp (unchanged!) tip runs with our own UID as effective UID, can access only our own normally accessed files. No additional permissions. 54

314 What is "saved set-uid"? 4. tip executes setuid(uucpuid) uucpuid was saved by calling geteuid() when tip started This call is allowed because the saved set-uid == uucpuid! Real UID = our own UID (unchanged!) Effective UID = uucp Saved set-uid = uucp (unchanged!) 5. tip can now release lock files because its efffective UID == uucp! 55

315 setreuid() setregid() #include <sys/types.h> #include <unistd.h> int setreuid(uid_t ruid, uid_t euid); int setregid(gid_t rgid, gid_t egid ); Both return: 0 if OK, -1 on error An unprivileged user can always swap between the real user ID and effective user ID For swapping real ID ßà effective ID 56

316 seteuid() setegid() #include <sys/types.h> #include <unistd.h> int seteuid(uid_t uid); int setegid(gid_t gid); Both return: 0 if OK, -1 on error An unprivileged user can set its effective user ID to either its real user ID or its saved set-user-id For a privileged user only the effective user ID is set to uid Only effective UID or GID is changed 57

317 Summary of set ID functions superuser setreuid(ruid, euid) superuser setuid(uid) superuser seteuid(uid) ruid euid uid uid uid uid real user ID unpriviliged setreuid effective user ID unpriviliged setreuid saved set-user-id exec of set-user-id unpriviliged setuid or seteuid unpriviliged setuid or seteuid 58

318 9. system() #include <stdlib.h> int system(const char *cmdstring); Causes the string to be given to sh(1) as input as if the string had been typed as a command at a terminal ex) system("date > file"); System is implemented by calling fork, exec, and waitpid Return values: -1 with errno: fork or waitpid fails 127 : exec fails Termination status of shell: all 3 succeed 59

319 #include <sys/types.h> /* system.c */ #include <sys/wait.h> #include <errno.h> #include <unistd.h> int system(const char *cmdstring) /* version without signal handling */ { pid_t pid; int status; if (cmdstring == NULL) return(1); /* always a command processor with Unix */ if ( (pid = fork()) < 0) { status = -1; /* probably out of processes */ } else if (pid == 0) { /* child */ execl("/bin/sh", "sh", "-c", cmdstring, (char *) 0); _exit(127); /* execl error */ } } else { /* parent */ while (waitpid(pid, &status, 0) < 0) if (errno!= EINTR) { status = -1; /* error other than EINTR from waitpid() */ break; } } return(status); 60

320 10. Process Times #include <sys/times.h> clock_t times(struct tms *buf); Returns: elapsed wall clock time in clock ticks if OK, -1 on error struct tms ( clock_t tms_utime; /* user cpu time */ clock_t tms_stime; /* system cpu time */ clock_t tms_cutime; /* child user cpu time */ clock_t tms_cstime; /* child system cpu time */ } 61

321 Wall clock time: the amount of time the process takes to run and depends on the system loads. The wall clock time returned is measured from some arbitrary point in the past. Use its relative value. User CPU time: attributed to user instructions System CPU time: attributed to the kernel, when it executes on behalf of the process 62

322 #include <sys/times.h> /* times1.c */ #include "ourhdr.h" static void pr_times(clock_t, struct tms *, struct tms *); static void do_cmd(char *); int main(int argc, char *argv[]) { int i; for (i = 1; i < argc; i++) do_cmd(argv[i]); /* once for each command-line arg */ exit(0); } static void do_cmd(char *cmd) /* execute and time the "cmd" */ { struct tms tmsstart, tmsend; clock_t start, end; int status; fprintf(stderr, "\ncommand: %s\n", cmd); if ( (start = times(&tmsstart)) == -1) /* starting values */ err_sys("times error"); if ( (status = system(cmd)) < 0) /* execute command */ err_sys("system() error"); if ( (end = times(&tmsend)) == -1) /* ending values */ err_sys("times error"); pr_times(end-start, &tmsstart, &tmsend); pr_exit(status); } 63

323 static void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend) { static long clktck = 0; if (clktck == 0) /* fetch clock ticks per second first time */ if ( (clktck = sysconf(_sc_clk_tck)) < 0) err_sys("sysconf error"); fprintf(stderr, " real: %7.2f\n", real / (double) clktck); fprintf(stderr, " user: %7.2f\n", (tmsend->tms_utime - tmsstart->tms_utime) / (double) clktck); fprintf(stderr, " sys: %7.2f\n", (tmsend->tms_stime - tmsstart->tms_stime) / (double) clktck); fprintf(stderr, " child user: %7.2f\n", (tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck); fprintf(stderr, " child sys: %7.2f\n", (tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck); } 64

324 Results: times1.c $ a.out "sleep 5" "date" command: sleep 5 real: 5.25 user: 0.00 sys: 0.00 child user: 0.02 child sys: 0.13 normal termination, exit status = 0 command: date Sun Aug 18 09:25:38 MST 1991 real: 0.27 user: 0.00 sys: 0.00 child user: 0.05 child sys: 0.10 normal termination, exit status = 0 65

325 고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 8장. 프로세스 관계 (Process Relationship)

326 Contents 1. Terminal Logins 2. Network Logins 3. Process Groups 4. Sessions 5. Controlling Terminal 6. Job Control 7. Orphaned Process 2

327 1. Terminal Logins: programs & files /etc/ttys: 1 line per terminal device getty: opens terminal device for reading and writing gettytab: data file for getty login: login program getpass: read password crypt: encrypts plain text (password) 3

328 To allow terminal logins process ID 1 init fork init exec getty /reads/etc/ttys; forks once per terminal; create empty environment; each child execs getty 4

329 State after login process ID 1 init fork init exec getty exec login /reads/etc/ttys; forks once per terminal; create empty environment; each child execs getty open terminal device (file descriptors 0, 1, 2); reads user name; initial environment set 5

330 All set for terminal login process ID 1 init login shell fd 0, 1, 2 terminal device driver through getty and login user at a termina l RS-232 connection 6

331 2. Network Logins inetd - Internet superserver waits for TCP/IP connection requests when request arrives, does a fork and exec of the appropriate program TELNET a remote login application that uses the TCP protocol. telnetd TELNET server opens pseudo-terminal device splits into two processes using fork The parent handles the communication across the network connection The child does an exec of the login program. 7

332 TELNET server TCP connection request from TELNET client process ID 1 init inetd fork inetd exec telnet d fork /exec of /bin/sh which executes shell script /etc/rc when system comes up multiuser when connection request arrives from TELNET client 8

333 All set for network login process ID 1 init login shell through inetd, telnetd, and login fd 0, 1, 2 pseudo-terminal device driver user at a termina l network connection through telnetd server and telnet client 9

334 3. Process Groups #include <sys/types.h> #include <unistd.h> pid_t getpgrp(void); Returns: process GID of calling process Process GID = PID à process group leader 10

335 Process Groups A process can create a process group and become leader A process group leader can create processes in the group A process group exists till the last process terminates OR joins another process group (leader may terminate first) 11

336 Process Groups #include <sys/types.h> #include <unistd.h> int setpgid(pid_t pid, pid_t pgid); Returns: 0 if OK, -1 on error Join existing group or create new group Sets process GID of a process with PID pid to pgid. 12

337 Process Groups pid == pgid à leader pid == 0 à pgid := PID of caller pgid == 0 à pgid := pid Process can set its own PGID or PGID of its children Both parent and child use setpgid to set their own process GIDs 13

338 4. Sessions login shell proc1 proc2 proc3 proc4 process group process group session proc5 process group Session = Collection of one or more process groups proc1 proc2 & proc3 proc4 proc5 14

339 Sessions #include <sys/types.h> #include <unistd.h> pid_t setsid(void); Returns: PGID if OK, -1 on error A process (not a process group leader) creates a new session: Process becomes session leader (new session contains this process only) Process become process group leader of a new process group (PGID=PID) Process has no controlling terminal. 15

340 Sessions Process group leader calling setsid() returns ERROR Solution to ensure not leader: fork() a child (new pid, parent gpid, not a process group leader) parent exits child continues as parent 16

341 5. Controlling Terminal Session has a controlling terminal Session leader is controlling process Process groups: 1 foreground, 1 or more background Interrupt key à quit key to all foreground processes Modem disconnect à hangup signal to controlling process 17

342 Controlling Terminal session login shell proc1 proc2 proc3 proc4 background process group session leader = controlling process background process group proc5 foreground process group modem disconnect (hangup signal) terminal input and terminal-generated signals controlling terminal 18

343 Controlling Terminal To talk to controlling terminal open /dev/tty (fails if no controlling terminal) Example crypt < salaries lpr stdin of crypt = salaries Qs: crypt needs password, how to input it? Ans: input password using controlling terminal by opening /dev/tty 19

344 tcgetpgrp() tcsetpgrp() #include <sys/types.h> #include <unistd.h> pid_t tcgetpgrp(int filedes); Returns: PGID of foreground process group if OK, -1 on error int tcsetpgrp(int filedes, pid_t pgrpid); Returns: 0 if OK, -1 on error tcgetpgrp returns PGID of foreground process group associated with the terminal open on filedes tcsetpgrp set the foreground process group ID to pgrpid only the process that has a controlling terminal can call this Normally called by job-control shells. 20

345 6. Job Control A feature added by Berkeley in 1980 To start multiple jobs (groups of processes) from a single terminal and To control: which jobs can access terminal which jobs are to run in background. 21

346 Job Control 3 forms of support required by job control: A shell to support job control Terminal driver must support job control Must support job-control signals _POSIX_JOB_CONTROL defines whether a system support job control Examples: vi main.c ß 1 foreground process pr *.c lpr & make all & ß 2 background processes 22

347 Job Control Shells assign a job identifier to a background job $ make all > Make.out & [1] 1475 $ pr *.c lpr & [2] 1490 process IDs of 1st process $ [2] + Done pr *.c lpr & [1] + Done make all > Make.out & job number 23

348 Job Control Terminal driver looks out for 3 special characters: Interrupt character (DELETE or CTRL-C) generates SIGINT Quit character (CTRL-BACKSLASH) generates SIGQUIT Suspend character (CTRL-Z) generates SIGTSTP SIGTTIN When background job tries to read from the terminal, the terminal driver detects this and sends it to the background job. SIGTTOU When background job tries to write to the terminal 24

349 Job Control $ cat temp.foo & [1] 1719 $ hello, world [1] + Done cat temp.foo & $ stty tostop $ cat temp.foo & [1] 1721 $ [1] + Stopped(tty output) cat temp.foo & $ fg %1 cat temp.foo hello, world 25

350 Job Control fg command The shell places the job into the foreground process group (tcsetpgrp) And sends SIGCONT to the process group stty command stty tostop disable ability of background jobs to output to the controlling terminal 26

351 Job Control 27

352 Job Control init or inetd getty or telnetd login exec login shell change in status of children setpgid setpgid exec, after setsid, then establishing controlling terminal change in status of children background process group(s) tcsetpgrp to set process group for controlling terminal write to terminal may generate SIGTTOU terminal input/output foreground process group Read from terminal generate SGITTIN terminal driver user at a terminal terminal-generated signals (SIGINT, SIGQUIT, SIGSTP) delivered to process group 28

353 7. Orphaned Process Groups What happens if a child is stopped (using job control) when parent terminates? How will the child ever be continued? Does the child know it has been orphaned? POSIX.1 definition of Orphaned Process Group: Parent of every process in a group is either itself a process in the group or is not a process in the group s session Not orphaned as long as a process has a parent in the same session 29

354 Orphaned Process Groups process group 442 login shell (PID 442) session fork/exec parent (PID 512) fork child (PID 513) process group

355 Orphaned Process Groups A stopped process in an orphaned process group is sent: the hang-up signal (SIGHUP), and the continue signal (SIGCONT) SIGHUP default action: terminate When parent terminates, child becomes a background process read from ctrl terminal à error is returned (errno:= EIO==5) 31

356 고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 9장. 시그널 (Signal)

357 Contents 1. Signal Concepts 2. signal() 3. Interrupted System Calls 4. Reentrant Functions 5.Reliable Signal Terminology and Semantics 6. kill() raise() 7. alarm() pause() 8. Signal Sets 9. sigprocmask() 10. sigpending() 11. sigaction() 12. sigsetjmp() siglongjmp() 13. sigsuspend() 2

358 Contents 14. abort() 15. sleep() 16. Job-Control Signals 3

359 1. Signal Concepts Signals are software interrupts Handles asynchronous events user typing CTRL-C to stop a program next program in pipeline terminated prematurely Every signal has a name begin with 'SIG' SIGABRT: abort signal from abort() SIGALRM: alarm signal from alarm() SVR4, 4.3+BSD: 31 different signals 4

360 Signal Concepts Signals are all defined by positive integer constants (the signal number) in the header <signal.h> Version 7 had 15 different signals Unreliable signal model - get lost and hard to turn off. SVR4 and 4.3+BSD both have 31 different signals Reliable signals added. 5

361 Signal Generation Terminal-generated signals DELETE or CTRL-C à SIGINT Hardware exceptions generate signals divide by 0 à SIGFPE invalid memory reference à SIGSEGV kill(2) function sends any signal to a process or process group need to be owner or superuser kill(1) command sends signal to a processes Software conditions: SIGALRM: alarm clock expires SIGPIPE: broken pipe SIGURG: out-of-band network data 6

362 Dispositions of signals Disposition or action: Process has to tell the kernel if and when this signal occurs, do the following. Ignore the signal: all signals can be ignored, except SIGKILL and SIGSTOP Catch the signal: Call a function of ours when a signal occurs. Let the default action apply most are to terminate process 7

363 Unix Signals SIGART: generated by calling the abort function. SIGALRM: generated when a timer set with the alarm expires. SIGCHLD : Whenever a process terminates or stops, the signal is sent to the parent. SIGCONT : This signal(job-control) sent to a stopped process when it is continued. SIGFPE : signals an arithmetic exception, such as divide-by-0, floating point overflow, and so on SIGHUP : disconnect detected, session leader terminates, daemon processes reread configuration files 8

364 Unix Signals SIGILL : indicates that the process has executed an illegal hardware instruction. SIGINT : generated by the terminal driver when we type the interrupt key and sent to all processes in the foreground process group SIGIO : indicates an asynchronous I/O event SIGKILL : can t be caught or ignored. a sure way to kill any process. SIGPIPE : If we write to a pipeline but the reader has terminated, SIGPIPE is generated SIGPWR : related to power failure. (read the book for the detail) SIGQUIT : generated by the terminal driver when we type terminal quit key and sent to all processes in the foreground process group 9

365 Unix Signals SIGSEGV : indicates that the process has made an invalid memory reference SIGSTOP : This signal(job-control) stops a process and can t be caught or ignored SIGSYS : signals an invalid system call SIGTERM : the termination signal sent by the kill(1) command by default. SIGTSTP : This is the interactive stop signal generated by the terminal driver when we type the terminal suspend key and sent to all processes in the foreground process group. SIGTTIN : generated by the terminal driver when a process in a background process group tries to read from its controlling terminal SIGTTOU : generated by the terminal driver when a process in a background process group tries to write to its controlling terminal 10

366 Unix Signals SIGURG : notifies the process that an urgent condition has occurred. Optionally generated when out-of-band data is received on a network connection. SIGUSR1, SIGUSR2 : user-defined signals, for use in application programs SIGWINCH : generated to the foreground process group when a process changes the window size from its previous value, with the ioctl set-window-size command SIGXCPU : generated if the process exceeds its soft CPU time limit SIGXFSZ : generated if the process exceeds its soft file size limit 11

367 2. signal() #include <signal.h> void ( *signal ( int signo, void (*func) (int))) (int) Returns: previous disposition of signal if OK, SIG_ERR on error signo : the name of the signal func: user-defined function (signal handler) called when the signal occurs. SIG_IGN - ignore the signal SIG_DFL - take its default action The signal handler is passed a single integer argument (the signal number) and returns nothing. signal() returns the pointer to the previous signal handler 12

368 #include <signal.h> /* sigusr.c */ #include "ourhdr.h" static void sig_usr(int signo) /* argument is signal number */ { if (signo == SIGUSR1) } printf("received SIGUSR1\n"); else if (signo == SIGUSR2) printf("received SIGUSR2\n"); else err_dump("received signal %d\n", signo); return; int main(void) { if (signal(sigusr1, sig_usr) == SIG_ERR) err_sys("can't catch SIGUSR1"); if (signal(sigusr2, sig_usr) == SIG_ERR) err_sys("can't catch SIGUSR2"); } for ( ; ; ) pause(); 13

369 sigusr.c: Results $ a.out & n[1] 4720 $ kill USR received SIGUSR1 $ kill USR received SIGUSR2 $ kill 4720 [1] + Terminated a.out & 14

370 Program Startup When a process is forked, the child inherits the parent s signal dispositions. When a program is execed the disposition of any signals that are being caught à default action the status of all other signals (ignored or default) à left alone 15

371 An interactive shell sets the disposition of the interrupt and quit signals in the background process to be ignored Many interactive programs catches the signals only when not in the background by doing the following: int sig_int(), sig_quit(); if (signal(sigint, SIG_IGN)!= SIG_IGN) signal(sigint, sig_int); if (signal(sigquit, SIG_IGN)!= SIG_IGN) signal(sigquit, sig_quit); 16

372 Signal disposition on fork On fork: Child inherits parent s signal dispositions Old signal handler has meaning in child 17

373 3. Interrupted System Calls A process is blocked in a slow system call The process receives a signal The system call is interrupted and returns an error (errno = EINTR) May be something happened that should wake up the blocked system call 18

374 Interrupted System Calls Slow system calls reads from/writes to files that can block the caller forever (pipes, terminal, network) open files that block until some condition occurs (opening terminal devices that waits until a modem answers the phone) pause() and wait() certain ioctl() operations and some IPC functions 19

375 Interrupted System Calls Need to restart an interrupted system call Again: if ((n = read(fd, buff, BUFFSIZE)) < 0) { if (errno == EINTR) goto Again; /* just an interrupted system call */ /* handle other errors */ } 20

376 Interrupted System Calls Automatic restarting of certain interrupted system calls (4.2BSD) ioctl, read, readv, write, and writev are interrupted by a signal only if they are operating on a slow device wait, waitpid are always interrupted when a signal is caught 4.3BSD allow to disable this feature on a per-signal basis Without the automatic restart feature, we need to test every read/write for the interrupted error return and reissue the read or write. 21

377 4. Reentrant Functions Process is executing Signal arrives and is caught Signal handler starts executing Signal handler returns Process resumes execution Any problem? 22

378 Reentrant Functions What if process was in the middle of malloc(), signal handler starts executing and also calls malloc()? malloc() maintains a linked list of all allocated areas process may have been in the middle of updating the linked list! 23

379 Reentrant Functions POSIX.1 specifies the functions that are guaranteed to be reentrant Reentrant Functions Functions that can be called by two or more processes (tasks, signal handlers), with arbitrary preemption (interrupt), and still give the same predictable output results Reentrancy conditions Use static variables in an atomic way, Do not call malloc or free, Does not belong to standard I/O library 24

380 Reentrant Functions Signal handlers should only call reentrant functions! Problems still exist: errno variable: updated by reentrant functions such as read(), wait(), etc. signal handler should save errno, and restore it on exit 25

381 #include <pwd.h> /* reenter.c */ #include <signal.h> #include "ourhdr.h" static void my_alarm(int signo) { struct passwd *rootptr; } printf("in signal handler\n"); if ( (rootptr = getpwnam("root")) == NULL) /* nonreenterant function call */ err_sys("getpwnam(root) error"); alarm(1); return; int main(void) { struct passwd *ptr; signal(sigalrm, my_alarm); alarm(1); /* generates SIGALRM after 1 sec */ } for ( ; ; ) { if ( (ptr = getpwnam("stevens")) == NULL) err_sys("getpwnam error"); if (strcmp(ptr->pw_name, "stevens")!= 0) printf("return value corrupted!, pw_name = %s\n", ptr->pw_name); } 26

382 reenter.c: Results Results are random Usually terminated by SIGSEGV Internal pointers corrupted when signal handler also called getpwnam() after main called it Sometimes terminated correctly, but return value corrupted, invalid file descriptor error (EBADF) returned 27

383 5.Reliable Signal Terminology and Semantics Signal is generated when event that causes the signal occurs hardware exception (divide by 0) software condition (alarm timer expiring) terminal-generated signal call to kill function Kernel sets a flag in the process table indicating that the signal is generated Signal is delivered to a process if action for signal is taken 28

384 Reliable Signal Terminology and Semantics During the time between the generation of signal and its delivery, the signal is said to be pending. Each process has a signal mask that defines the set of signals currently blocked from delivery to that process 29

385 Reliable Signal Terminology and Semantics A blocked signal remains pending when: default signal action, or catch signal using user-defined handler A signal stops being pending when: unblocks the signal, or changes the action to ignore the signal What to do with blocked signals is determined when it is delivered and not when it is generated (to change action) 30

386 6. kill() raise() #include <sys/types.h> #include <singnal.h> int kill(pid_t pid, int signo); int raise(int signo); Both return: 0 if OK, 1 on error kill - sends a signal to a process or a group of process raise - function allows a process to send a signal to itself 31

387 kill() pid > 0 : signal to the process whose process ID is pid pid == 0 : signal to the processes whose process group ID equals that of sender pid < 0 : signal to the processes whose process group ID equals abs. of pid pid == -1 : POSIX.1 leaves this condition unspecified (used as a broadcast signal in SVR4, 4.3+BSD) 32

388 kill() - Permission to send signals The superuser can send a signal to any process The real or effective user ID of the sender has to equal the real or effective user ID of the receiver If _POSIX_SAVED_IDS is defined, the saved set-user-id of the receiver is checked instead of its effective user ID. SIGCONT can be sent to any member process of the same session 33

389 kill() - Sending NULL signal NULL signal: signo == 0 Sent with kill for error checking e.g. to check if a process exists no signal is sent If the process doesn t exist, kill returns 1 and errno is set to ESRCH 34

390 7. alarm() #include <unistd.h> unsigned int alarm (unsigned int seconds); Returns: 0 or number of seconds until previously set alarm alarm() sets a timer to expire at a specified time in future when timer expires, SIGALRM signal is generated, default action of the signal is to terminate the process. seconds is the number of clock seconds in the future when the signal should be generate scheduling delays may occur 35

391 alarm() only one alarm clock per process previously registered alarm clock is replaced by the new value if alarm(0), a previous unexpired alarm is cancelled 36

392 pause() #include <unistd.h> int pause (void); Returns: -1 with errno set to EINTR suspends the calling process until a signal is caught. returns only if a signal handler is executed and that handler returns. 37

393 using alarm and pause to implement sleep #include <signal.h> /* sleep1.c */ #include <unistd.h> static void sig_alrm(int signo) { return; /* nothing to do, just return to wake up the pause */ } unsigned int sleep1(unsigned int nsecs) { if (signal(sigalrm, sig_alrm) == SIG_ERR) return nsecs; alarm(nsecs); /* start the timer */ pause(); /* next caught signal wakes us up */ return alarm(0); /* turn off timer, return unslept time */ } 38

394 sleep1.c: Implementation Problems If the caller of sleep1() already has an alarm set, the alarm is erased by the first call to alarm. Modify the disposition for SIGALRM Save the disposition and restore it when we're done Race condition: between alarm & pause the signal handler may be called before pause the alarm goes off before the pause() the called is suspended forever at pause() 39

395 Another implementation of sleep #include <setjmp.h> /* sleep2.c */ #include <signal.h> #include <unistd.h> static jmp_buf env_alrm; static void sig_alrm(int signo) { longjmp(env_alrm, 1); } unsigned int sleep2(unsigned int nsecs) { if (signal(sigalrm, sig_alrm) == SIG_ERR) return nsecs; if (setjmp(env_alrm) == 0) { alarm(nsecs); /* start the timer */ pause(); /* next caught signal wakes us up */ } return alarm(0); /* turn off timer, return unslept time */ } 40

396 sleep2.c: Implementation Problems The previous race condition was avoided Another problem if SIGALRM interrupts some other signal handler and the longjmp() aborts the other signal handler (see the next example) 41

397 Calling sleep2 #include <signal.h> /* tsleep2.c */ #include "ourhdr.h" unsigned int sleep2(unsigned int); static void sig_int(int signo) { int i; volatile int j; } printf("\nsig_int starting\n"); for (i = 0; i < ; i++) j += i * i; printf("sig_int finished\n"); return; int main(void) { unsigned int unslept; } if (signal(sigint, sig_int) == SIG_ERR) err_sys("signal(sigint) error"); unslept = sleep2(5); printf("sleep2 returned: %u\n", unslept); exit(0); 42

398 tsleep2.c: Results $ a.out sleep2 starts running ^? Type our interrupt char sig_int starting SIGALRM generated while in sig_int() sleep2 returned: 0 longjmp aborted sig_int 43

399 alarm: Timeout on blocking operations A read operation on a "slow" device can block for a long time An upper time limit can be imposed using the alarm function and SIGALRM 44

400 Timeout #include <signal.h> /* read1.c */ #include "ourhdr.h" static void sig_alrm(int signo) { return; /* nothing to do, just return to interrupt the read */ } int main(void) { int n; char line[maxline]; if (signal(sigalrm, sig_alrm) == SIG_ERR) err_sys("signal(sigalrm) error"); alarm(10); if ( (n = read(stdin_fileno, line, MAXLINE)) < 0) err_sys("read error"); alarm(0); } write(stdout_fileno, line, n); exit(0); 45

401 read1.c A common use for alarm : timeout function Race condition: alarm may go off before read() If the read system call is automatically restarted, the read is not interrupted when the SIGALRM signal handler returns timeout does not work. 46

402 Another Timeout #include <setjmp.h> /* read2.c */ #include <signal.h> #include "ourhdr.h" static jmp_buf env_alrm; static void sig_alrm(int signo) { longjmp(env_alrm, 1); } int main(void) { int n; char line[maxline]; if (signal(sigalrm, sig_alrm) == SIG_ERR) err_sys("signal(sigalrm) error"); if (setjmp(env_alrm)!= 0) err_quit("read timeout"); alarm(10); if ( (n = read(stdin_fileno, line, MAXLINE)) < 0) err_sys("read error"); alarm(0); } write(stdout_fileno, line, n); exit(0); 47

403 read2.c No problems with automatic restart But still has the race condition and the problem with other signal handler interactions 48

404 8. Signal Sets datatype to represent multiple signals (sigset_t) the five functions to manipulate signal sets #include <signal.h> int sigemptyset (sigset_t *set); int sigfillset (sigset_t *set); int sigaddset (sigset_t *set, int signo); int sigdelset (sigset_t *set, int signo); all four return: 0 if OK, -1 on error int sigismember ( const sigset_t *set, int signo); Returns:1 if true, 0 if false 49

405 Functions to manipulate signal sets sigemptyset initialize set so that all signals are excluded sigfillset initialize set so that all signals are included sigaddset add a single signal to an existing set sigdelset remove a single signal from a set sigismember test if signal is a member of a signal set 50

406 9. sigprocmask() #include <signal.h> int sigprocmask(int how, const sigset_t *set, sigset_t *oset); Returns: 0 if OK, -1 on error Examine or change signals to be blocked 1. if oset!= NULL, the current signal mask is returned through oset 2. if set!= NULL, how SIG_BLOCK : block the signal in set SIG_UNBLOCK : unblock the signals in set SIG_SETMASK : the new signal mask = set 51

407 #include <errno.h> /* prmask.c */ #include <signal.h> #include "ourhdr.h" void pr_mask(const char *str) { sigset_t sigset; int errno_save; errno_save = errno; /* we can be called by signal handlers */ if (sigprocmask(0, NULL, &sigset) < 0) err_sys("sigprocmask error"); } printf("%s", str); if (sigismember(&sigset, SIGINT)) printf("sigint "); if (sigismember(&sigset, SIGQUIT)) printf("sigquit "); if (sigismember(&sigset, SIGUSR1)) printf("sigusr1 "); if (sigismember(&sigset, SIGALRM)) printf("sigalrm "); /* remaining signals can go here */ printf("\n"); errno = errno_save; 52

408 10. sigpending() #include <signal.h> int sigpending (sigset_t *set); Returns: 0 if OK, -1 on error returns the set of signals that are blocked and pending returned through the set argument 53

409 #include <signal.h> /* critical.c */ #include "ourhdr.h" static void sig_quit(int signo) { printf("caught SIGQUIT\n"); if (signal(sigquit, SIG_DFL) == SIG_ERR) err_sys("can't reset SIGQUIT"); return; } int main(void) { sigset_t newmask, oldmask, pendmask; } if (signal(sigquit, sig_quit) == SIG_ERR) err_sys("can't catch SIGQUIT"); sigemptyset(&newmask); sigaddset(&newmask, SIGQUIT); /* block SIGQUIT and save current signal mask */ if (sigprocmask(sig_block, &newmask, &oldmask) < 0) err_sys("sig_block error"); sleep(5); /* SIGQUIT here will remain pending */ if (sigpending(&pendmask) < 0) err_sys("sigpending error"); if (sigismember(&pendmask, SIGQUIT)) printf("\nsigquit pending\n"); /* reset signal mask which unblocks SIGQUIT */ if (sigprocmask(sig_setmask, &oldmask, NULL) < 0) err_sys("sig_setmask error"); printf("sigquit unblocked\n"); sleep(5); /* SIGQUIT here will terminate with core file */ exit(0); 54

410 critical.c : Results $ a.out ^\ SIGQUIT pending caught SIGQUIT SIGQUIT unblocked ^\Quit(coredump) 55

411 11. sigaction() #include <signal.h> int sigaction (int signo, const struct sigaction *act, struct sigaction *oact); Returns:0 if OK, -1 on error examines or modify the action associated with a particular signal supersedes the signal function from earlier UNIX signo : signal number If act!= NULL, we are modifying the action If oact!= NULL, the system returns the previous action for the signal 56

412 sigaction() struct sigaction { void (*sa_handler)(); /* address of signal handler */ sigset_t sa_mask; /* additional signals to block */ int sa_flags; /* signal options */ }; sa_handler : address of signal handler, SIG_IGN, or SIG_DFL sa_mask : additional signals to block when the signal handler is called sa_flags : option flags for the handling each signal 57

413 Option flags (sa_flags) SA_NOCLDSTOP : If signo is SIGCHLD, do not generate this signal when a child process stops (job control) SA_RESTART : System calls interrupted by this signal are automatically restarted SA_ONSTACK : If an alternate stack has been declared with sigaltstack(2), this signal is delivered to the process on the alternate stack SA_NOCLDWAIT : If signo is SIGCHID, this option causes the system not to create zombie processes when children terminate 58

414 Option flags (sa_flags) SA_NODEFER : When this signal is caught, the signal is not automatically blocked by the system while the signal-catching function executes (unreliable!) SA_RESETHAND : The disposition for this signal is reset to SIG_DFL on entry to the signal-catching function. Note that this type of operation corresponds to the earlier unreliable signals SA_SIGINFO : This option provides additional information to a signal handler 59

415 Implementation of signal using sigaction #include <signal.h> /* signal.c */ #include "ourhdr.h" Sigfunc * signal(int signo, Sigfunc *func) { struct sigaction act, oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (signo == SIGALRM) { #ifdef SA_INTERRUPT act.sa_flags = SA_INTERRUPT; /* SunOS */ #endif } else { #ifdef SA_RESTART act.sa_flags = SA_RESTART; /* SVR4, 44BSD */ #endif } if (sigaction(signo, &act, &oact) < 0) return(sig_err); return(oact.sa_handler); } 60

416 12. sigsetjmp() siglongjmp() #include <set jmp.h> int sigsetjmp (sigjmp_buf env, int savemask) ; Returns: 0 if called directly, nonzero if returning from a call to siglongjmp int siglongjmp (sigjmp_buf env, int val) ; When a signal is caught, the signal is added to the signal mask What happens to the signal mask for the process if we longjmp out of the signal handler? sigsetjmp and siglongjmp saves and restores the signal mask if savemask!= 0, sigsetjmp saves the current signal mask in env use these functions for nonlocal branching from a signal handler 61

417 #include <signal.h> /* mask.c */ #include <setjmp.h> #include <time.h> #include "ourhdr.h" static void sig_usr1(int), sig_alrm(int); static sigjmp_buf jmpbuf; static volatile sig_atomic_t canjump; int main(void) { if (signal(sigusr1, sig_usr1) == SIG_ERR) err_sys("signal(sigusr1) error"); if (signal(sigalrm, sig_alrm) == SIG_ERR) err_sys("signal(sigalrm) error"); pr_mask("starting main: "); /* {Prog prmask} */ } if (sigsetjmp(jmpbuf, 1)) { pr_mask("ending main: "); exit(0); } canjump = 1; /* now sigsetjmp() is OK */ for ( ; ; ) pause(); 62

418 static void sig_usr1(int signo) { time_t starttime; if (canjump == 0) return; /* unexpected signal, ignore */ pr_mask("starting sig_usr1: "); alarm(3); /* SIGALRM in 3 seconds */ } starttime = time(null); for ( ; ; ) /* busy wait for 5 seconds */ if (time(null) > starttime + 5) break; pr_mask("finishing sig_usr1: "); canjump = 0; siglongjmp(jmpbuf, 1); /* jump back to main, don't return */ static void sig_alrm(int signo) { pr_mask("in sig_alrm: "); return; } 63

419 mask.c: Results $ a.out & start process in background starting main: [1] 531 the job-control shell prints its process ID $ kill USR1 531 send the process SIGUSR1 starting sig_usr1: SIGUSR1 $ in sig_alrm: SIGUSR1 SIGALRM finishing sig_usr1: SIGUSR1 ending main: [1] + Done a.out & 64

420 13. sigsuspend() #include <signal.h> int sigsuspend (const sigset_t *sigmask) ; Returns: -1 with errno set to EINTR Reset the signal mask and put the process to sleep in a single atomic operation Signal mask of the process is set to sigmask suspended until a signal is caught or until a signal occurs that terminates the process If a signal is caught and if the signal handler returns, then sigsuspend returns and the signal mask of the process is set to its value before the call to sigsuspend 65

421 sigsuspend() sigset_t newmask, oldmask; sigemptyset(&newmask); sigaddset(&newmask, SIGINT); /* block SIGINT and save current signal mask */ if (sigprocmask(sig_block, &newmask, &oldmask) < 0) err_sys("sig_block error"); /* critical region of code */ /* reset signal mask which unblocks SIGINT */ if (sigprocmask(sig_setmask, &oldmask, NULL) < 0) err_sys("sig_setmask error"); pause(); /* wait for signal to occur */ /* and continue processing... */ Protect critical regions of code from interrupt signals Problem if the signal occurs between the unblocking and the pause. any occurrence of the signal in this window of time is lost we need a way to both Reset the signal mask and put the process to sleep in a single atomic operation 66

422 #include <signal.h> /* suspend1.c */ #include "ourhdr.h" static void sig_int(int signo) { pr_mask("\nin sig_int: "); return; } int main(void) { sigset_t newmask, oldmask, zeromask; } if (signal(sigint, sig_int) == SIG_ERR) err_sys("signal(sigint) error"); sigemptyset(&zeromask); sigemptyset(&newmask); sigaddset(&newmask, SIGINT); /* block SIGINT and save current signal mask */ if (sigprocmask(sig_block, &newmask, &oldmask) < 0) err_sys("sig_block error"); /* critical region of code */ pr_mask("in critical region: "); /* allow all signals and pause */ if (sigsuspend(&zeromask)!= -1) err_sys("sigsuspend error"); pr_mask("after return from sigsuspend: "); /* reset signal mask which unblocks SIGINT */ if (sigprocmask(sig_setmask, &oldmask, NULL) < 0) err_sys("sig_setmask error"); /* and continue processing... */ exit(0); 67

423 14. abort() #include <stdlib.h> void abort(void); This function never returns Causes abnormal program termination This function sends the SIGABRT signal to the process SIGABRT signal handler to perform any cleanup that it wants to do, before the process terminated POSIX.1 states that if the process does not terminate itself from this signal handler, when signal handler returns, abort terminates the process. 68

424 15. sleep() #include <signal.h> unsigned int sleep(unsigned int seconds) ; Returns: 0 or number of unslept seconds This function causes the calling process to be suspended until either The amount of wall clock time specified by second has elapsed (returns 0) A signal is caught by the process and the signal handler returns (returns the number of unslept seconds) The actual return may be at a time later than requested, because of other system activity 69

425 16. Job-Control Signals SIGCHLD : Child process has stopped or terminated SIGCONT : Continue process, if stopped SIGSTOP : Stop signal (can t be caught or ignored) SIGTSTP : Interactive stop signal SIGTTIN : Read from controlling terminal by a background process group SIGTTOUT: Write to controlling terminal by member of a background process group A program that manages the terminal needs to handle job-control signals When type Control-Z (suspend Character), SIGTSTP sent to all processes in the foreground process group. 70

426 #include <signal.h> /* sigtstp.c */ #include "ourhdr.h" #define BUFFSIZE 1024 static void sig_tstp(int); int main(void) { int n; char buf[buffsize]; /* only catch SIGTSTP if we're running with a job-control shell */ if (signal(sigtstp, SIG_IGN) == SIG_DFL) signal(sigtstp, sig_tstp); } while ( (n = read(stdin_fileno, buf, BUFFSIZE)) > 0) if (write(stdout_fileno, buf, n)!= n) err_sys("write error"); if (n < 0) err_sys("read error"); exit(0); 71

427 static void sig_tstp(int signo) /* signal handler for SIGTSTP */ { sigset_t mask; /*... move cursor to lower left corner, reset tty mode... */ /* unblock SIGTSTP, since it's blocked while we're handling it */ sigemptyset(&mask); sigaddset(&mask, SIGTSTP); sigprocmask(sig_unblock, &mask, NULL); signal(sigtstp, SIG_DFL); /* reset disposition to default */ kill(getpid(), SIGTSTP); /* and send the signal to ourself */ /* we won't return from the kill until we're continued */ signal(sigtstp, sig_tstp); /* reestablish signal handler */ } /*... reset tty mode, redraw screen... */ return; 72

428 고급 시스템 프로그래밍 (소프트웨어 개발 트랙) 10장. 프로세스간 통신 (Interprocess Communication)

429 Contents 1. Pipes 2. FIFOs 3. System V IPC 4. message queues 5. semaphores 6. shared memory 2

430 1. Pipes In UNIX, pipes are the oldest form of IPC Limitations of Pipes: Half duplex (data flows in one direction) Can only be used between processes that have a common ancestor (Usually used between the parent and child processes) Processes cannot pass pipes and must inherit them from their parent If a process creates a pipe, all its children will inherit it 3

431 Pipes In a UNIX shell, the pipe symbol is: (the vertical bar) In a shell, UNIX pipes look like: $ ls -alg more where the standard output of the program at the left (i.e., the producer) becomes the standard input of the program at the right (i.e., the consumer). We can have longer pipes: $ pic paper.ms tbl eqn ditroff -ms 4

432 Pipes #include <unistd.h> int pipe(int filedes[2]) Returns: 0 if OK, -1 on error two file descriptors are returned through the filedes argument filedes[0] : can be used to read from the pipe, and filedes[1] : can be used to write to the pipe Anything that is written on filedes[1] may be read by filedes[0] This is of no use in a single process. However, between processes, it gives a method of communication The pipe() system call gives parent-child processes a way to communicate with each other 5

433 Pipes user process parent fork child fd[0] fd[1] fd[0] fd[1] fd[0] fd[1] pipe kernel pipe kernel 6

434 Pipes parent à child: parent closes fd[0] child closes fd[1] parent ß child: parent closes fd[1] child closes fd[0] parent child parent child fd[1] fd[0] fd[0] fd[1] pipe kernel pipe kernel 7

435 Pipes Read from a pipe with write end closed: returns 0 to indicate EOF Write to a pipe with read end closed: SIGPIPE generated, write() returns error (errno == EPIPE) A write of PIPE_BUF (kernel s pipe buffer size) bytes or less will not be interleaved with the writes from other processes atomic write 8

436 #include "ourhdr.h" /* pipe1.c */ int main(void) { int n, fd[2]; pid_t pid; char line[maxline]; if (pipe(fd) < 0) err_sys("pipe error"); if ( (pid = fork()) < 0) err_sys("fork error"); else if (pid > 0) { /* parent */ close(fd[0]); write(fd[1], "hello world\n", 12); } else { /* child */ close(fd[1]); n = read(fd[0], line, MAXLINE); write(stdout_fileno, line, n); } } exit(0); 9

437 popen() pclose() #include <stdio.h> FILE *popen(const char *cmdstring, const char *type); Returns: file pointer if OK, NULL on error int pclose(file *fp); Returns: termination status of cmdstring, or 1 on error handle all the dirty work the creation of a pipe, the fork of a child, closing the unused ends of the pipe, execing a shell to execute the command, and waiting for the command to terminate popen does a fork and exec to execute the cmdstring and returns a file pointer. 10

438 popen() pclose() fp = popen(cmdstring, "r"); parent cmdstring(child) fp stdout fp = popen(cmdstring, "w"); parent cmdstring(child) fp stdin 11

439 #include <sys/wait.h> /* popen1.c */ #include "ourhdr.h" int main(void) { char line[maxline]; FILE *fpin; if ( (fpin = popen("myuclc", "r")) == NULL) err_sys("popen error"); } for ( ; ; ) { fputs("prompt> ", stdout); fflush(stdout); if (fgets(line, MAXLINE, fpin) == NULL) /* read from pipe */ break; if (fputs(line, stdout) == EOF) err_sys("fputs error to pipe"); } if (pclose(fpin) == -1) err_sys("pclose error"); putchar('\n'); exit(0); 12

440 2. FIFOs Pipes can be used only between related processes FIFOs are "named pipes" that can be used between unrelated processes A type of file stat.st_mode == FIFO Test with S_ISFIFO macro 13

441 FIFOs #include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode); Returns: 0 if OK, -1 on error Creating FIFOs is similar to creating a file pathname : filename mode: permissons, same as for open() function Using a FIFO is similar to using a file we can open, close, read, write, unlink, etc., to the FIFO 14

442 FIFOs if FIFO opened without O_NONBLOCK flag an open for read-only blocks until some other process opens the FIFO for writing an open for write-only blocks until some other process opens the FIFO for reading if O_NONBLOCK is specified (nonblocking) an open for read-only returns immediately if no process has the FIFO open for writing an open for write-only returns an error (errno=enxio) if no process has the FIFO open for reading 15

443 FIFOs Like a pipe, if we write to a FIFO that no process has open for reading, the signal SIGPIPE is generated When the last writer for a FIFO closes the FIFO, an end of file is generated for the reader of the FIFO. PIPE_BUF specifies the maximum amount of data that can be written atomically to a FIFO writes from multiple process are not interleaved 16

444 Uses of FIFOs Used by shell commands to pass data from one shell pipeline to another, without creating intermediate files Used in client-server application to pass data between clients and server 17

445 Using FIFOs to Duplicate Output Streams tee(1) copies its standard input to both its standard output and to the file named on its command line $ mkfifo fifo1 $ prog3 < fifo1 & $ prog1 < infile tee fifo1 prog2 fifo1 prog3 infile prog1 tee prog2 18

446 Client-Server Communication Using a FIFO Server creates a "well-known" FIFO to communicate with clients To avoid interleaving of client data, client must write at most PIPE_BUF bytes at a time Problem: Server can't reply clients using a single "well-known" FIFO 19

447 Client-Server Communication Using a FIFO client write request... well-known FIFO read request server client write request 20

448 Client-Server Communication Using a FIFO Create a FIFO for each client such that server can reply using the client-specific FIFO e.g.: /tmp/serv1.xxxx, where XXXXX is client s process ID Impossible for server to know if a client has crashed FIFOs left in system Server must catch SIGPIPE (FIFO with 1 writer, no reader) it's possible for a client to send a request and terminate before reading the response, leaving the client-specific FIFO with one writer (the server) and no reader 21

449 Client-Server Communication Using a FIFO client read replies write request client-specific FIFO write replies... well-known FIFO read request server client write request read replies client-specific FIFO write replies 22

450 3. System V IPC Message Queues Semaphores Shared Memory Each IPC structure has a nonnegative integer identifier (large!) When creating an IPC structure, a key must be specified (type: key_t) 23

451 Identifiers and Keys Server creates a new IPC structure using key = IPC_PRIVATE Server stores returned identifier in some file for client to obtain Disadvantage: file I/O! 24

452 Identifiers and Keys Define a key in a common header Client and server agree to use that key Server creates a new IPC structure using that key Problem: key exists? (msgget, semget, shmget returns error) Solution: delete existing key, create a new one again! 25

453 Identifiers and Keys Client and server agree on a pathname a project ID (char between 0 ~ 255) ftok() converts the 2 values into a key Client and server use that key (cf. 2) Disadvantage: ftok à a function call! 26

454 Permission Structure struct ipc_perm { uid_t uid; /* owner's effective user id */ gid_t gid; /* owner's effective group id */ uid_t cuid; /* creator's effective user id */ gid_t cgid; /* creators' effective group id */ mode_t mode; /* access modes */ ulong seq; /* slot usage sequence number */ key_t key; /* key */ }; 27

455 System V IPC permissions Permission Message queue Semaphore Shared memory user-read MSG_R SEM_R SHM_R user-write (alter) MSG_W SEM_W SHM_W group-read MSG_R >> 3 SEM_R >> 3 SHM_R >> 3 group-write (alter) MSG_W >> 3 SEM_W >> 3 SHM_W >> 3 other-read MSG_R >> 6 SEM_R >> 6 SHM_R >> 6 other-write (alter) MSG_W >> 6 SEM_W >> 6 SHM_W >> 6 ipc_perm.mode 28

456 Comparison of features IPC type connectionless? reliable? flow control? records? message queue no yes yes yes yes streams no yes yes yes yes Unix stream socket no yes yes no no Unix datagram socket yes yes no yes no FIFOs no yes yes no no message types or priorities? 29

457 4. Message Queues Linked list of messages Stored in kernel Identified by message queue identifier msgget: create new or open existing queue nmsgsnd: add new msg to a queue msgrcv: receive msg from a queue Fetching order: based on type 30

458 Message Queues Each queue has a structure struct msqid_ds { struct ipc_perm msg_perm; struct msg *msg_first; /* ptr to first msg on queue */ struct msg *msg_last; /* ptr to last msg on queue */ ulong msg_cbytes; /* current # bytes on queue */ ulong msg_qnum; /* # msgs on queue */ ulong msg_qbytes; /* max # bytes on queue */ pid_t msg_lspid; /* pid of last msgsnd() */ pid_t msg_lrpid; /* pid of last msgrcv() */ time_t msg_stime; /* last-msgsnd() time */ time_t msg_rtime; /* last-msgrcv() time */ time_t msg_ctime; /* last-change time */ }; 31

459 System limits on queues Name Description Typical Value MASMAX The size in bytes of the largest message we can send MSGMNB MSGMNI The maximum size in bytes of a particular queue (i.e., the sum of all the message on the queue) The maximum number of messages queues, systemwide 4096 MSGTQL The maximum number of messages, systemwide

460 msgget() #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgget(key_t key, int flag); Returns: msg queue ID if OK, -1 on error create new or open existing queue flag : ipc_perm.mode 33

461 msgctl() #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgctl(int msqid, int cmd, struct msqid_ds *buf); Returns: 0 if OK, -1 on error performs various operations on a queue 34

462 msgctl() cmd IPC_STAT : Fetch the msqid_ds structure for this queue, storing it in buf IPC_SET : Set the following four fields from buf: msg_perm.uid, msg_perm.gid, msg_perm.mode, msg_qbytes IPC_RMID : Remove the message queue and any data still on the queue 35

463 msgsnd() #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int msqid, const void *ptr, size_t nbytes, int flag); Returns: 0 if OK, -1 on error place a message at the end of the queue ptr points to a message nbytes : length of message data 36

464 msgsnd() struct mymesg { long mtype; /* positive message type */ char mtext[512]; /* message data, of length nbytes */ }; A flag value of IPC_NOWAIT is similar to the nonblocking I/O flag for file I/O 37

465 msgrcv() #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flag); Returns: data size in message if OK, -1 on error retrieve a message from a queue type == 0 : the first message on the queue is returned type > 0 : the first message on the queue whose message type equals type is returned type < 0 : the first message on the queue whose message type is the lowest value less than or equal to the absolute value of type is returned 38

466 Comparision between Queues vs. Stream Pipes test program create IPC channel, call fork, then send 20 MB data from parent to child using 10,000 calls to msgsnd with a message length of 2,000 bytes Operation SPARC, SunOS , SVR4 User System Clock User System Clock message queue stream pipe

467 5. Semaphores A counter to provide access to shared data object for multiple processes To object a shared resource: 1. Test semaphore controlling resource 2. If value > 0, value--, grant use 3. If value == 0, sleep until value > 0 4. Release resource, value ++ Step 1, 2 must be an atomic operation 40

468 System V Semaphores A semaphore is defined as a set of one or more semaphore values Creation (semget) is independent of initialization (semctl) All IPCs exist even if no process is using them. Need worry about process terminating without releasing semaphore. 41

469 Semaphore structure struct semid_ds { struct ipc_perm sem_perm; struct sem *sem_base; /*ptr to first semaphore in set */ ushort sem_nsems; /* # of semaphors in set */ time_t sem_otime; /* last-semop() time */ time_t sem_ctime; /* last-change time */ }; struct sem { ushort semval; /* semaphore value, always >= 0 */ pid_t sempid; /* pid for last operation */ ushort semncnt; /* # processes awaiting semval > currval */ ushort semzcnt; /* # processes awaiting semval = 0 */ }; 42

470 semget() #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semget(key_t key, int nsems, int flag); Returns: semaphore ID if OK, -1 on error obtain a semaphore ID nsems : sem_nsens flag : ipc_perm.mode 43

471 setctl() #include <sys/types.h> #include <sys/ipc.h> #include <sys/sem.h> int semctl(int semid, int semnum, int cmd, union semun arg); union semun { int val; /* for SETVAL */ struct semid_ds *buf; /* for IPC_START and IPC_SET */ ushort *array; /* for GETALL and SETALL */ }; 44

472 setctl() - cmd IPC_STAT: fetch the semid_ds structure into arg.buf IPC_SET: set the following three fields from arg.buf: sem_perm.uid, sem_perm.gid, sem_perm.mode IPC_RMID: remove the semaphore set from the system GETVAL: return the value of semval for the member semnum SETVAL: set the value of semval for the member semnum GETPID: return the value of sempid for the member semnum GETNCNT: return the value of semncnt GETZCNT: return the value of semzcnt GETALL: fetch all the semaphore values in the set into arg.array SETALL: set all the semaphore values in the set from arg.array 45

473 Comparison between semaphore vs. record locking Operation SPARC, SunOS , SVR4 User System Clock User System Clock semaphore with undo advisory record locking

474 6. Shared Memory Fastest form of IPC: no need of data copying between client & server Must synchronize access to a shared memory segment Semaphores are used 47

475 Shared Memory Segment Structure struct shmid_ds { struct ipc_perm shm_perm; struct anon_map *shm_amp; /* pointer in kernel */ int shm_segsz; /* size of segment in bytes */ ushort shm_lkcnt; /* # of times segment is being locked */ pid_t shm_lpid; /* pid of last shmop() */ pid_t shm_cpid; /* pid of creator */ ulong shm_nattch; /* # of current attaches */ ulong shm_cnattch; /* used only for shminfo() */ time_t shm_atime; /* last-attach time */ time_t shm_dtime; /* last-detach time */ time_t shm_ctime; /* last-change time */ }; 48

476 shmget() #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, int size, int flag); Returns: shared memory ID if OK, -1 on error obtain a shared memory identifier size : is the size of the shared memory segment flag : ipc_perm.mode 49

477 shmctl() #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> int shmctl(int shmid, int cmd, struct shmid_ds *buf); Returns: 0 if OK, -1 on error various shared memory operations 50

478 shmctl() - cmd IPC_STAT: fetch the shmid_ds structure into buf IPC_SET: set the following three fields from buf: shm_perm.uid, shm_perm.gid, shm_perm.mode IPC_RMID: remove the shared memory segment set from the system SHM_LOCK: Lock the shared memory segment in memory SHM_UNLOCK: Unlock the shared memory segment 51

479 shmat() #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> void *shmat (int shmid, void *addr, int flag); Returns: pointer to shared memory segment if OK, -1 on error attached a shared memory to an address flag SHM_RDONLY : the segment is read-only 52

480 shmat() addr==0: at the first address selected by the kernel recommended addr!=0 && SHM_RND is not specified: at the address given by addr addr!=0 && SHM_RND is specified: at the address given by (addr (addr modulus SHMLBA)) 53

481 shmdt() #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> void shmdt (void *addr); Returns: 0 if OK, -1 on error detach a shared memory segment 54

482 #include <sys/types.h> /* tshm.c */ #include <sys/ipc.h> #include <sys/shm.h> #include "ourhdr.h" #define ARRAY_SIZE #define MALLOC_SIZE #define SHM_SIZE #define SHM_MODE (SHM_R SHM_W) /* user read/write */ char array[array_size]; /* uninitialized data = bss */ int main(void) { int shmid; char *ptr, *shmptr; printf("array[] from %x to %x\n", &array[0], &array[array_size]); printf("stack around %x\n", &shmid); if ( (ptr = malloc(malloc_size)) == NULL) err_sys("malloc error"); printf("malloced from %x to %x\n", ptr, ptr+malloc_size); if ( (shmid = shmget(ipc_private, SHM_SIZE, SHM_MODE)) < 0) err_sys("shmget error"); if ( (shmptr = shmat(shmid, 0, 0)) == (void *) -1) err_sys("shmat error"); printf("shared memory attached from %x to %x\n", shmptr, shmptr+shm_size); } if (shmctl(shmid, IPC_RMID, 0) < 0) err_sys("shmctl error"); exit(0); 55

483 Results: $ a.out array[] from 18f48 to 22b88 stack around f7fffb2c malloced from 24c28 to 3d2c8 shared memory attached from f77d0000 to f77e86a0 56

484 Memory Layout high address stack command-line arguments and environment variables 0xf7fffb2c shared memory 0xf77e86a0 0xf77d0000 shared memory of 100,000 bytes heap uninitialized data (bss) initialized data 0x0003d2c8 0x00024c28 0x0003d2c8 0x00024c28 malloc of 100,000 bytes array[] of 40,000 bytes low address text 57

chap7.key

chap7.key 1 7 C 2 7.1 C (System Calls) Unix UNIX man Section 2 C. C (Library Functions) C 1975 Dennis Ritchie ANSI C Standard Library 3 (system call). 4 C?... 5 C (text file), C. (binary file). 6 C 1. : fopen( )

More information

슬라이드 1

슬라이드 1 / 유닉스시스템개요 / 파일 / 프로세스 01 File Descriptor file file descriptor file type unix 에서의파일은단지바이트들의나열임 operating system 은파일에어떤포맷도부과하지않음 파일의내용은바이트단위로주소를줄수있음 file descriptor 는 0 이나양수임 file 은 open 이나 creat 로 file

More information

Microsoft PowerPoint APUE(File InO).ppt

Microsoft PowerPoint APUE(File InO).ppt 컴퓨터특강 () [Ch. 3] 2006 년봄학기 문양세강원대학교컴퓨터과학과 강의목표및내용 강의목표 파일의특성을이해한다. 파일을열고닫는다. 파일로부터데이터를읽고쓴다. 기타파일제어함수를익힌다. 강의내용 파일구조 (UNIX 파일은어떤구조일까?) 파일관련시스템호출 시스템호출의효율과구조 Page 2 1 What is a File? A file is a contiguous

More information

Microsoft PowerPoint APUE(File InO)

Microsoft PowerPoint APUE(File InO) Linux/UNIX Programming 문양세강원대학교 IT특성화대학컴퓨터과학전공 강의목표및내용 강의목표 파일의특성을이해한다. 파일을열고닫는다. 파일로부터데이터를읽고쓴다. 기타파일제어함수를익힌다. 강의내용 파일구조 (UNIX 파일은어떤구조일까?) 파일관련시스템호출 시스템호출의효율과구조 Page 2 What is a File? A file is a contiguous

More information

제1장 Unix란 무엇인가?

제1장  Unix란 무엇인가? 5 장파일시스템 상지대학교컴퓨터공학과고광만 [email protected] http://compiler.sangji.ac.kr 2018 5.1 파일시스템구현 파일시스템구조 0 1 2 3 200 201 부트블록슈퍼블록 i-노드 1..40 i-노드 41..80... 데이터블록데이터블록... i- 리스트 데이터블록 데이터블록 3 파일시스템구조 부트블록 (Boot

More information

Microsoft PowerPoint APUE(File InO).pptx

Microsoft PowerPoint APUE(File InO).pptx Linux/UNIX Programming 문양세강원대학교 IT대학컴퓨터과학전공 강의목표및내용 강의목표 파일의특성을이해한다. 파일을열고닫는다. 파일로부터데이터를읽고쓴다. 기타파일제어함수를익힌다. 강의내용 파일구조 (UNIX 파일은어떤구조일까?) 파일관련시스템호출 시스템호출의효율과구조 Page 2 What is a File? A file is a contiguous

More information

Microsoft PowerPoint - chap2

Microsoft PowerPoint - chap2 제 2 장. 파일입출력 (File I/O) 숙대창병모 1 목표 파일의구조및특성을이해한다. 파일을열고닫는다. 파일로부터데이터를읽고쓴다. 파일현재위치변경 기타파일제어 숙대창병모 2 2.1 파일구조 숙대창병모 3 What is a file? a file is a contiguous sequence of bytes no format imposed by the operating

More information

10.

10. 10. 10.1 10.2 Library Routine: void perror (char* str) perror( ) str Error 0 10.3 10.3 int fd; /* */ fd = open (filename, ) /*, */ if (fd = = -1) { /* */ } fcnt1 (fd, ); /* */ read (fd, ); /* */ write

More information

Microsoft PowerPoint - chap13-입출력라이브러리.pptx

Microsoft PowerPoint - chap13-입출력라이브러리.pptx #include int main(void) int num; printf( Please enter an integer: "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); return 0; 1 학습목표 스트림의 기본 개념을 알아보고,

More information

Microsoft PowerPoint - chap4 [호환 모드]

Microsoft PowerPoint - chap4 [호환 모드] 제 5 장 C 표준라이브러리 숙대창병모 1 목표 C 표준라이브러리의깊이있는이해 시스템호출과 C 표준라이브러리관계 숙대창병모 2 C 입출력라이브러리함수 숙대창병모 3 시스템호출과라이브러리함수 System Calls well defined entry points directly into the kernel documented in section 2 of the

More information

제1장 Unix란 무엇인가?

제1장  Unix란 무엇인가? 4 장파일 컴퓨터과학과박환수 1 2 4.1 시스템호출 컴퓨터시스템구조 유닉스커널 (kernel) 하드웨어를운영관리하여다음과같은서비스를제공 파일관리 (File management) 프로세스관리 (Process management) 메모리관리 (Memory management) 통신관리 (Communication management) 주변장치관리 (Device

More information

歯9장.PDF

歯9장.PDF 9 Hello!! C printf() scanf() getchar() putchar() gets() puts() fopen() fclose() fprintf() fscant() fgetc() fputs() fgets() gputs() fread() fwrite() fseek() ftell() I/O 2 (stream) C (text stream) : `/n'

More information

제12장 파일 입출력

제12장 파일 입출력 제 4 장파일입출력 리눅스시스템프로그래밍 청주대학교전자공학과 한철수 1 시스템호출 (system call) 파일 (file) 임의접근 (random access) 주요학습내용 2 4.1 절 커널의역할 (kernel) 커널 (kernel) 은운영체제의핵심부분으로서, 하드웨어를운영관리하는여러가지서비스를제공함 파일관리 (File management) 디스크 프로세스관리

More information

<4D F736F F F696E74202D FC6C4C0CFB0FA20B5F0B7BAC5E4B8AE205BC8A3C8AF20B8F0B5E55D>

<4D F736F F F696E74202D FC6C4C0CFB0FA20B5F0B7BAC5E4B8AE205BC8A3C8AF20B8F0B5E55D> 학습목표 유닉스파일의특징을이해한다. 파일에관한정보를검색하는함수를사용할수있다. 하드링크와심볼릭링크파일을이해하고관련함수를사용할수있다. 파일사용권한을검색하고조정하는함수를사용할수있다. 디렉토리의특징을이해한다. 디렉토리의내용을검색하는함수를사용할수있다. 디렉토리를생성하고삭제하는함수를사용할수있다. 파일과디렉토리 IT CookBook, 유닉스시스템프로그래밍 2/45 목차

More information

Microsoft PowerPoint APUE(Intro).ppt

Microsoft PowerPoint APUE(Intro).ppt 컴퓨터특강 () [Ch. 1 & Ch. 2] 2006 년봄학기 문양세강원대학교컴퓨터과학과 APUE 강의목적 UNIX 시스템프로그래밍 file, process, signal, network programming UNIX 시스템의체계적이해 시스템프로그래밍능력향상 Page 2 1 APUE 강의동기 UNIX 는인기있는운영체제 서버시스템 ( 웹서버, 데이터베이스서버

More information

제1장 Unix란 무엇인가?

제1장  Unix란 무엇인가? 7 장 C 표준파일입출력 컴퓨터과학과박환수 1 2 7.1 파일및파일포인터 시스템호출과 C 라이브러리함수 시스템호출 (System Calls) Unix 커널에서비스요청하는호출 UNIX man의 Section 2에설명되어있음 C 함수처럼호출될수있음. C 라이브러리함수 (Library Functions) C 라이브러리함수는보통시스템호출을포장해놓은함수 보통내부에서시스템호출을함

More information

C 프로그래밍 언어 입문 C 프로그래밍 언어 입문 김명호저 숭실대학교 출판국 머리말..... C, C++, Java, Fortran, Python, Ruby,.. C. C 1972. 40 C.. C. 1999 C99. C99. C. C. C., kmh ssu.ac.kr.. ,. 2013 12 Contents 1장 프로그래밍 시작 1.1 C 10 1.2 12

More information

로봇SW교육원 강의자료

로봇SW교육원 강의자료 UNIT 06 파일 I/O 로봇 SW 교육원 3 기 학습목표 2 저수준파일입출력함수를사용핛수있다. 리눅스파일시스템을이해핚다. 다양핚파일입출력실습을통해프로그램능력을향상핚다. 파일디스크립터 3 파일디스크립터를통해파일의 I/O처리 음이아닊정수 표준입력, 표준출력, 표준에러의파일서술자 unistd.h STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO

More information

Microsoft PowerPoint - chap12 [호환 모드]

Microsoft PowerPoint - chap12 [호환 모드] 제 12 장고급입출력 Nov 2007 숙대창병모 1 Contents 1. Nonblocking I/O 2. Record Locking 3. Memory Mapped I/O Nov 2007 숙대창병모 2 12.1 Nonblocking I/O Nov 2007 숙대창병모 3 Nonblocking I/O Blocking I/O I/O 작업완료를기다리며영원히리턴안할수있다

More information

6주차.key

6주차.key 6, Process concept A program in execution Program code PCB (process control block) Program counter, registers, etc. Stack Heap Data section => global variable Process in memory Process state New Running

More information

로봇SW교육원 강의자료

로봇SW교육원 강의자료 UNIT 05 make 광운대학교로봇 SW 교육원 최상훈 학습목표 2 Makefile 을작성핛수있다. make 3 make 프로젝트관리유틸리티 컴파일시갂단축 파일의종속구조를빠르게파악핛수있음 기술파일 (Makefile) 에기술된대로컴파일명령또는셸 (shell) 명령을순차적으로수행 make 를사용하지않을경우 $ gcc c main.c $ gcc c test_a.c

More information

2009년 상반기 사업계획

2009년 상반기 사업계획 파일입출력 IT CookBook, 유닉스시스템프로그래밍 학습목표 유닉스에서파일입출력의특징을이해한다. 저수준파일입출력함수를사용할수있다. 고수준파일입출력함수를사용할수있다. 임시파일을생성해파일입출력을할수있다. 2/51 목차 저수준파일입출력 파일기술자 파일생성과열고닫기 파일읽기와쓰기 파일오프셋지정 파일기술자복사 파일기술자제어 파일삭제 고수준파일입출력 파일포인터 파일열기와닫기

More information

학번 : 이름 : 1. 다음파일트리구조를가진유닉스시스템이있다고가정하자. / /bin/ /home/ /home/taesoo/ /usr/ /usr/lib/ /usr/local/lib /media 모든폴더에파일이하나도없다고가정했을때사용자가터미널에서다음 ls 명령입력시화면출력

학번 : 이름 : 1. 다음파일트리구조를가진유닉스시스템이있다고가정하자. / /bin/ /home/ /home/taesoo/ /usr/ /usr/lib/ /usr/local/lib /media 모든폴더에파일이하나도없다고가정했을때사용자가터미널에서다음 ls 명령입력시화면출력 학번 : 이름 : 1. 다음파일트리구조를가진유닉스시스템이있다고가정하자. / /bin/ /home/ /home/taesoo/ /usr/ /usr/lib/ /usr/local/lib /media 모든폴더에파일이하나도없다고가정했을때사용자가터미널에서다음 ls 명령입력시화면출력을예측하시오. $ cd /usr $ ls..? $ ls.? 2. 다음그림은어떤프로세스가다음코드를수행했다는가정에서도시되었다.

More information

금오공대 컴퓨터공학전공 강의자료

금오공대 컴퓨터공학전공 강의자료 C 프로그래밍프로젝트 Chap 24. 파일입출력 2013.11.27. 오병우 컴퓨터공학과 파일 (File) 입출력 표준입출력 vs. 파일입출력 HDD 프로그래머입장에서는동일한방법으로입출력 다만 file 을읽고쓰기전에 Open 해서스트림에대한파일포인터 (file pointer) 를얻어야한다. OS 가실제작업을대행하며, 프로그래머는적절한함수를적절한방법으로호출 Department

More information

Microsoft PowerPoint - Lecture 4-1 Linux File Environment.ppt [호환 모드]

Microsoft PowerPoint - Lecture 4-1 Linux File Environment.ppt [호환 모드] Liux Programmig Sprig 2008 File Hadlig Importat cotets Liux 에서 C 컴파일방법 File 처리프로그래밍 Liux 환경접근프로그래밍 Kogju Natioal Uiversity Liux System Programmig 2/29 Basic compilig method Liux C Compiler : gcc, cc 기본

More information

제1장 Unix란 무엇인가?

제1장  Unix란 무엇인가? 1 12 장파이프 2 12.1 파이프 파이프원리 $ who sort 파이프 3 물을보내는수도파이프와비슷 한프로세스는쓰기용파일디스크립터를이용하여파이프에데이터를보내고 ( 쓰고 ) 다른프로세스는읽기용파일디스크립터를이용하여그파이프에서데이터를받는다 ( 읽는다 ). 한방향 (one way) 통신 파이프생성 파이프는두개의파일디스크립터를갖는다. 하나는쓰기용이고다른하나는읽기용이다.

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 ERROR AND COMMAND LINE ARGUMENTS Jo, Heeseung 학습목표 오류처리함수 동적메모리할당 명령행인자 2 오류처리함수 [1] 오류메시지출력 : perror(3) #include void perror(const char *s); [ 예제 1-4] perror 함수사용하기 01 #include

More information

Microsoft PowerPoint - 제11강 파일 처리

Microsoft PowerPoint - 제11강 파일 처리 제13장 파일 처리 파일열기 : File Open FILE *fp; fp=fopen( filename, r ); File handling mode: r, w, a, rb, wb, ab, r+, w+, a+ fclose(fp) 파일의종류 : Text File, Binary File Text file:.txt,.doc,.hwp Binary file:.exe,.jpg,.gif,.mov,.mpeg,.tif,.pgm,.ppm.

More information

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx #include int main(void) { int num; printf( Please enter an integer "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); return 0; } 1 학습목표 을 작성하면서 C 프로그램의

More information

K&R2 Reference Manual 번역본

K&R2 Reference Manual 번역본 typewriter structunion struct union if-else if if else if if else if if if if else else ; auto register static extern typedef void char short int long float double signed unsigned const volatile { } struct

More information

프로그램을 학교 등지에서 조금이라도 배운 사람들을 위한 프로그래밍 노트 입니다. 저 역시 그 사람들 중 하나 입니다. 중고등학교 시절 학교 도서관, 새로 생긴 시립 도서관 등을 다니며 책을 보 고 정리하며 어느정도 독학으르 공부하긴 했지만, 자주 안하다 보면 금방 잊어

프로그램을 학교 등지에서 조금이라도 배운 사람들을 위한 프로그래밍 노트 입니다. 저 역시 그 사람들 중 하나 입니다. 중고등학교 시절 학교 도서관, 새로 생긴 시립 도서관 등을 다니며 책을 보 고 정리하며 어느정도 독학으르 공부하긴 했지만, 자주 안하다 보면 금방 잊어 개나리 연구소 C 언어 노트 (tyback.egloos.com) 프로그램을 학교 등지에서 조금이라도 배운 사람들을 위한 프로그래밍 노트 입니다. 저 역시 그 사람들 중 하나 입니다. 중고등학교 시절 학교 도서관, 새로 생긴 시립 도서관 등을 다니며 책을 보 고 정리하며 어느정도 독학으르 공부하긴 했지만, 자주 안하다 보면 금방 잊어먹고 하더라구요. 그래서,

More information

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D>

<4D F736F F F696E74202D20B8AEB4AABDBA20BFC0B7F920C3B3B8AEC7CFB1E22E BC8A3C8AF20B8F0B5E55D> 리눅스 오류처리하기 2007. 11. 28 안효창 라이브러리함수의오류번호얻기 errno 변수기능오류번호를저장한다. 기본형 extern int errno; 헤더파일 라이브러리함수호출에실패했을때함수예 정수값을반환하는함수 -1 반환 open 함수 포인터를반환하는함수 NULL 반환 fopen 함수 2 유닉스 / 리눅스 라이브러리함수의오류번호얻기 19-1

More information

untitled

untitled Step Motor Device Driver Embedded System Lab. II Step Motor Step Motor Step Motor source Embedded System Lab. II 2 open loop, : : Pulse, 1 Pulse,, -, 1 +5%, step Step Motor (2),, Embedded System Lab. II

More information

학번 : 이름 : 1. 다음파일트리구조를가진유닉스시스템이있다. / /bin/ /home/ /home/taesoo/ /home/taesoo/downloads /usr/ /usr/lib/ /usr/local/lib /media 모든폴더에파일이하나도없다고가정했을때사용자 (t

학번 : 이름 : 1. 다음파일트리구조를가진유닉스시스템이있다. / /bin/ /home/ /home/taesoo/ /home/taesoo/downloads /usr/ /usr/lib/ /usr/local/lib /media 모든폴더에파일이하나도없다고가정했을때사용자 (t 학번 : 이름 : 1. 다음파일트리구조를가진유닉스시스템이있다. / /bin/ /home/ /home/taesoo/ /home/taesoo/downloads /usr/ /usr/lib/ /usr/local/lib /media 모든폴더에파일이하나도없다고가정했을때사용자 (taesoo) 가터미널에서다음 ls 명령입력시화면출력을예측하시오. $ ls /usr/.. $

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 오픈소스소프트웨어개발입문 (CP33992) 파일입출력 부산대학교공과대학정보컴퓨터공학부 학습목표 파일의기본개념과특징을이해할수있다. 파일처리과정을이해할수있다. 형식을지정한파일입출력함수의사용법을알수있다. 2 파일과파일포인터 3 파일 C 의파일은모든데이터를연속된바이트형태로저장한다. 4 텍스트파일 (text file) C 언어의파일종류 사람들이읽을수있는문자들을저장하고있는파일

More information

Adobe Flash 취약점 분석 (CVE-2012-0754)

Adobe Flash 취약점 분석 (CVE-2012-0754) 기술문서 14. 08. 13. 작성 GNU C library dynamic linker $ORIGIN expansion Vulnerability Author : E-Mail : 윤지환 [email protected] Abstract 2010 년 Tavis Ormandy 에 의해 발견된 취약점으로써 정확한 명칭은 GNU C library dynamic linker

More information

BMP 파일 처리

BMP 파일 처리 BMP 파일처리 김성영교수 금오공과대학교 컴퓨터공학과 학습내용 영상반전프로그램제작 2 Inverting images out = 255 - in 3 /* 이프로그램은 8bit gray-scale 영상을입력으로사용하여반전한후동일포맷의영상으로저장한다. */ #include #include #define WIDTHBYTES(bytes)

More information

고급 프로그래밍 설계

고급 프로그래밍 설계 UNIT 09 표준 I/O 라이브러리 광운대학교로봇 SW 교육원 최상훈 시스템호출 vs 표준 I/O 라이브러리함수 2 Application code read write printf scanf Standard I/O Library buffer read, write User System Call System Buffer (buffer cache) Kernel sync

More information

Microsoft PowerPoint - ch09_파이프 [호환 모드]

Microsoft PowerPoint - ch09_파이프 [호환 모드] 학습목표 파이프를이용한 IPC 기법을이해한다. 이름없는파이프를이용해통신프로그램을작성할수있다. 이름있는파이프를이용해통신프로그램을작성할수있다. 파이프 IT CookBook, 유닉스시스템프로그래밍 2/20 목차 파이프의개념 이름없는파이프만들기 복잡한파이프생성 양방향파이프활용 이름있는파이프만들기 파이프의개념 파이프 두프로세스간에통신할수있도록해주는특수파일 그냥파이프라고하면일반적으로이름없는파이프를의미

More information

휠세미나3 ver0.4

휠세미나3 ver0.4 andromeda@sparcs:/$ ls -al dev/sda* brw-rw---- 1 root disk 8, 0 2014-06-09 18:43 dev/sda brw-rw---- 1 root disk 8, 1 2014-06-09 18:43 dev/sda1 brw-rw---- 1 root disk 8, 2 2014-06-09 18:43 dev/sda2 andromeda@sparcs:/$

More information

2009년 상반기 사업계획

2009년 상반기 사업계획 메모리매핑 IT CookBook, 유닉스시스템프로그래밍 학습목표 통신프로그램이무엇인지이해한다. 메모리매핑을이용한 IPC 기법을이해한다. 메모리매핑함수를사용해프로그램을작성할수있다. 2/20 목차 메모리매핑의개념 메모리매핑함수 메모리매핑해제함수 메모리매핑의보호모드변경 파일의크기확장 매핑된메모리동기화 데이터교환하기 3/20 메모리매핑의개념 메모리매핑 파일을프로세스의메모리에매핑

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 KeyPad Device Control - Device driver Jo, Heeseung HBE-SM5-S4210 에는 16 개의 Tack Switch 를사용하여 4 행 4 열의 Keypad 가장착 4x4 Keypad 2 KeyPad 를제어하기위하여 FPGA 내부에 KeyPad controller 가구현 KeyPad controller 16bit 로구성된

More information

3. 다음그림은프로세스의 file table 과 v-node 테이블의연결관계예제이다. 위그림을참고하여두개의서로다른프로세스가같은파일을 open 명령을사용하여열었을때의연결관계를도시하시오. 4. 메모리영역은 low-address 부터 high-adress 까지순서대로나열했을

3. 다음그림은프로세스의 file table 과 v-node 테이블의연결관계예제이다. 위그림을참고하여두개의서로다른프로세스가같은파일을 open 명령을사용하여열었을때의연결관계를도시하시오. 4. 메모리영역은 low-address 부터 high-adress 까지순서대로나열했을 학번 : 이름 : 1. 다음파일트리구조를가진유닉스시스템이있다. / /bin/ /home/ /home/taesoo/ /home/taesoo/downloads /usr/ /usr/lib/ /usr/local/lib /media 모든폴더에파일이하나도없다고가정했을때사용자 (taesoo) 가터미널에서다음 ls 명령입력시화면출력을예측하시오. $ ls /usr/. $ ls

More information

À©µµ³×Æ®¿÷ÇÁ·Î±×·¡¹Ö4Àå_ÃÖÁ¾

À©µµ³×Æ®¿÷ÇÁ·Î±×·¡¹Ö4Àå_ÃÖÁ¾ P a 02 r t Chapter 4 TCP Chapter 5 Chapter 6 UDP Chapter 7 Chapter 8 GUI C h a p t e r 04 TCP 1 3 1 2 3 TCP TCP TCP [ 4 2] listen connect send accept recv send recv [ 4 1] PC Internet Explorer HTTP HTTP

More information

C Programming

C Programming C Programming 파일입출력 Seo, Doo-okok [email protected] http://www.clickseo.com 목 차 파일입출력 파일입출력함수 파일처리함수 2 파일입출력 파일입출력 파일의이해 파일입출력의이해 파일입출력함수 파일처리함수 3 파일의이해 파일 (File) 하나의단위로취급해야하는데이터들의외부적컬렉션 파일의종류 텍스트파일 :

More information

API 매뉴얼

API 매뉴얼 PCI-DIO12 API Programming (Rev 1.0) Windows, Windows2000, Windows NT and Windows XP are trademarks of Microsoft. We acknowledge that the trademarks or service names of all other organizations mentioned

More information

13주-14주proc.PDF

13주-14주proc.PDF 12 : Pro*C/C++ 1 2 Embeded SQL 3 PRO *C 31 C/C++ PRO *C NOT! NOT AND && AND OR OR EQUAL == = SQL,,, Embeded SQL SQL 32 Pro*C C SQL Pro*C C, C Pro*C, C C 321, C char : char[n] : n int, short, long : float

More information

Chapter #01 Subject

Chapter #01  Subject Device Driver March 24, 2004 Kim, ki-hyeon 목차 1. 인터럽트처리복습 1. 인터럽트복습 입력검출방법 인터럽트방식, 폴링 (polling) 방식 인터럽트서비스등록함수 ( 커널에등록 ) int request_irq(unsigned int irq, void(*handler)(int,void*,struct pt_regs*), unsigned

More information

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과

임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과 임베디드시스템설계강의자료 6 system call 2/2 (2014 년도 1 학기 ) 김영진 아주대학교전자공학과 System call table and linkage v Ref. http://www.ibm.com/developerworks/linux/library/l-system-calls/ - 2 - Young-Jin Kim SYSCALL_DEFINE 함수

More information

제7장 C 표준 파일 입출력

제7장 C 표준 파일 입출력 제 7 장 C 표준파일입출력 리눅스시스템프로그래밍 청주대학교전자공학과 한철수 목차 파일및파일포인터 텍스트파일 이진파일 임의접근 버퍼입출력 기타함수 2 7.1 절 시스템호출과 C 라이브러리함수 응용프로그램이커널에서비스를요청하는방법 방법 1: 시스템호출 (system call) 을이용하여요청. 방법 2: C 언어가제공하는라이브러리함수를이용하여요청. 라이브러리함수는내부적으로시스템호출을이용함.

More information

Microsoft PowerPoint - 09_(C_Programming)_(Korean)_File_Processing

Microsoft PowerPoint - 09_(C_Programming)_(Korean)_File_Processing C Programming 파일처리 (File Processing) Seo, Doo-Ok Clickseo.com [email protected] 목 차 파일입출력 텍스트파일입출력함수 이진파일입출력함수 다양한파일처리함수 2 파일입출력 파일입출력 입출력스트림 파일과파일입출력 텍스트파일입출력함수 이진파일입출력함수 다양한파일처리함수 3 스트림 (Stream) 데이터의논리적흐름

More information

Microsoft Word - Network Programming_NewVersion_01_.docx

Microsoft Word - Network Programming_NewVersion_01_.docx 10. Unix Domain Socket 105/113 10. Unix Domain Socket 본절에서는 Unix Domain Socket(UDS) 에대한개념과이에대한실습을수행하고, 이와동시에비신뢰적인통신시스템의문제점에대해서분석하도록한다. 이번실습의목표는다음과같다. 1. Unix Domain Socket의사용법을익히고, IPC에대해서실습 2. TCP/IP의응용계층과전달계층의동작을구현및실습

More information

금오공대 컴퓨터공학전공 강의자료

금오공대 컴퓨터공학전공 강의자료 C 프로그래밍프로젝트 Chap 14. 포인터와함수에대한이해 2013.10.09. 오병우 컴퓨터공학과 14-1 함수의인자로배열전달 기본적인인자의전달방식 값의복사에의한전달 val 10 a 10 11 Department of Computer Engineering 2 14-1 함수의인자로배열전달 배열의함수인자전달방식 배열이름 ( 배열주소, 포인터 ) 에의한전달 #include

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 7-Segment Device Control - Device driver Jo, Heeseung HBE-SM5-S4210 의 M3 Module 에는 6 자리를가지는 7-Segment 모듈이아래그림처럼실장 6 Digit 7-Segment 2 6-Digit 7-Segment LED controller 16비트로구성된 2개의레지스터에의해제어 SEG_Sel_Reg(Segment

More information

The Pocket Guide to TCP/IP Sockets: C Version

The Pocket Guide to  TCP/IP Sockets: C Version 인터넷프로토콜 5 장 데이터송수신 (3) 1 파일전송메시지구성예제 ( 고정크기메시지 ) 전송방식 : 고정크기 ( 바이너리전송 ) 필요한전송정보 파일이름 ( 최대 255 자 => 255byte 의메모리공간필요 ) 파일크기 (4byte 의경우최대 4GB 크기의파일처리가능 ) 파일내용 ( 가변길이, 0~4GB 크기 ) 메시지구성 FileName (255bytes)

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 (Host) set up : Linux Backend RS-232, Ethernet, parallel(jtag) Host terminal Target terminal : monitor (Minicom) JTAG Cross compiler Boot loader Pentium Redhat 9.0 Serial port Serial cross cable Ethernet

More information

제7장 C 표준 파일 입출력

제7장 C 표준 파일 입출력 제 7 장 C 표준파일입출력 리눅스시스템프로그래밍 청주대학교전자공학과 한철수 1 목차 파일및파일포인터 텍스트파일 이진파일 임의접근 버퍼입출력 기타함수 2 7.1 절 시스템호출과 C 라이브러리함수 응용프로그램이커널에서비스를요청하는방법 방법 1: 시스템호출 (system call) 을이용하여요청함. 방법 2: C 언어가제공하는라이브러리함수를이용하여요청함. 라이브러리함수내에서시스템호출을이용하고있음.

More information

Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3

Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3 Poison null byte Excuse the ads! We need some help to keep our site up. List 1 Conditions 2 Exploit plan 2.1 chunksize(p)!= prev_size (next_chunk(p) 3 Example 3.1 Files 3.2 Source code 3.3 Exploit flow

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 7-Segment Device Control - Device driver Jo, Heeseung HBE-SM5-S4210 의 M3 Module 에는 6 자리를가지는 7-Segment 모듈이아래그림처럼실장 6 Digit 7-Segment 2 6-Digit 7-Segment LED Controller 16비트로구성된 2개의레지스터에의해제어 SEG_Sel_Reg(Segment

More information

강의10

강의10 Computer Programming gdb and awk 12 th Lecture 김현철컴퓨터공학부서울대학교 순서 C Compiler and Linker 보충 Static vs Shared Libraries ( 계속 ) gdb awk Q&A Shared vs Static Libraries ( 계속 ) Advantage of Using Libraries Reduced

More information

슬라이드 1

슬라이드 1 / 임베디드시스템개요 / 임베디드운영체제 / 디바이스드라이버 01 Linux System Architecture Application Area Application System Call Interface BSD Socket Virtual File System INET(AF_INET) Kernel Area Buffer Cache Network Subsystem

More information

컴파일러

컴파일러 YACC 응용예 Desktop Calculator 7/23 Lex 입력 수식문법을위한 lex 입력 : calc.l %{ #include calc.tab.h" %} %% [0-9]+ return(number) [ \t] \n return(0) \+ return('+') \* return('*'). { printf("'%c': illegal character\n",

More information

Microsoft PowerPoint - chap10-함수의활용.pptx

Microsoft PowerPoint - chap10-함수의활용.pptx #include int main(void) { int num; printf( Please enter an integer: "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); return 0; } 1 학습목표 중 값에 의한 전달 방법과

More information

SRC PLUS 제어기 MANUAL

SRC PLUS 제어기 MANUAL ,,,, DE FIN E I N T R E A L L O C E N D SU B E N D S U B M O TIO

More information

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070>

<443A5C4C C4B48555C B3E25C32C7D0B1E25CBCB3B0E8C7C1B7CEC1A7C6AE425CBED0C3E0C7C1B7CEB1D7B7A55C D616E2E637070> #include "stdafx.h" #include "Huffman.h" 1 /* 비트의부분을뽑아내는함수 */ unsigned HF::bits(unsigned x, int k, int j) return (x >> k) & ~(~0

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 7-SEGMENT DEVICE CONTROL - DEVICE DRIVER Jo, Heeseung 디바이스드라이버구현 : 7-SEGMENT HBE-SM5-S4210 의 M3 Module 에는 6 자리를가지는 7-Segment 모듈이아래그림처럼실장 6 Digit 7-Segment 2 디바이스드라이버구현 : 7-SEGMENT 6-Digit 7-Segment LED

More information

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F >

<4D F736F F F696E74202D20B8B6C0CCC5A9B7CEC7C1B7CEBCBCBCAD202839C1D6C2F7207E203135C1D6C2F > 10주차 문자 LCD 의인터페이스회로및구동함수 Next-Generation Networks Lab. 5. 16x2 CLCD 모듈 (HY-1602H-803) 그림 11-18 19 핀설명표 11-11 번호 분류 핀이름 레벨 (V) 기능 1 V SS or GND 0 GND 전원 2 V Power DD or V CC +5 CLCD 구동전원 3 V 0 - CLCD 명암조절

More information

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D313939392D382E687770>

<C0CCBCBCBFB52DC1A4B4EBBFF82DBCAEBBE7B3EDB9AE2D313939392D382E687770> i ii iii iv v vi 1 2 3 4 가상대학 시스템의 국내외 현황 조사 가상대학 플랫폼 개발 이상적인 가상대학시스템의 미래상 제안 5 웹-기반 가상대학 시스템 전통적인 교수 방법 시간/공간 제약을 극복한 학습동기 부여 교수의 일방적인 내용전달 교수와 학생간의 상호작용 동료 학생들 간의 상호작용 가상대학 운영 공지사항,강의록 자료실, 메모 질의응답,

More information

Microsoft PowerPoint - a10.ppt [호환 모드]

Microsoft PowerPoint - a10.ppt [호환 모드] Structure Chapter 10: Structures t and Macros Structure 관련된변수들의그룹으로이루어진자료구조 template, pattern field structure를구성하는변수 (cf) C언어의 struct 프로그램의 structure 접근 entire structure 또는 individual fields Structure는

More information

The Pocket Guide to TCP/IP Sockets: C Version

The Pocket Guide to  TCP/IP Sockets: C Version 얇지만얇지않은 TCP/IP 소켓프로그래밍 C 2 판 4 장 UDP 소켓 제 4 장 UDP 소켓 4.1 UDP 클라이언트 4.2 UDP 서버 4.3 UDP 소켓을이용한데이터송싞및수싞 4.4 UDP 소켓의연결 UDP 소켓의특징 UDP 소켓의특성 싞뢰할수없는데이터젂송방식 목적지에정확하게젂송된다는보장이없음. 별도의처리필요 비연결지향적, 순서바뀌는것이가능 흐름제어 (flow

More information

1217 WebTrafMon II

1217 WebTrafMon II (1/28) (2/28) (10 Mbps ) Video, Audio. (3/28) 10 ~ 15 ( : telnet, ftp ),, (4/28) UDP/TCP (5/28) centralized environment packet header information analysis network traffic data, capture presentation network

More information

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100

Microsoft PowerPoint - ch09 - 연결형리스트, Stack, Queue와 응용 pm0100 2015-1 프로그래밍언어 9. 연결형리스트, Stack, Queue 2015 년 5 월 4 일 교수김영탁 영남대학교공과대학정보통신공학과 (Tel : +82-53-810-2497; Fax : +82-53-810-4742 http://antl.yu.ac.kr/; E-mail : [email protected]) 연결리스트 (Linked List) 연결리스트연산 Stack

More information

ActFax 4.31 Local Privilege Escalation Exploit

ActFax 4.31 Local Privilege Escalation Exploit NSHC 2012. 12. 19. 취약점 분석 보고서 Information Service about a new vulnerability [ ] 목 차 1. 개 요... 2 2. 공 격... 5 3. 분 석... 9 4. 결 론... 12 5. 대응방안... 12 6. 참고자료... 13 Copyright 2012 Red Alert. All Rights Reserved.

More information

Microsoft PowerPoint - [2009] 02.pptx

Microsoft PowerPoint - [2009] 02.pptx 원시데이터유형과연산 원시데이터유형과연산 원시데이터유형과연산 숫자데이터유형 - 숫자데이터유형 원시데이터유형과연산 표준입출력함수 - printf 문 가장기본적인출력함수. (stdio.h) 문법 ) printf( Test printf. a = %d \n, a); printf( %d, %f, %c \n, a, b, c); #include #include

More information

106 107, ( ),, ( ), 3, int kor[5]; int eng[5]; int Microsoft Windows 4 (ANSI C2 ) int kor[5] 20 # define #define SIZE 20 int a[10]; char c[10]; float

106 107, ( ),, ( ), 3, int kor[5]; int eng[5]; int Microsoft Windows 4 (ANSI C2 ) int kor[5] 20 # define #define SIZE 20 int a[10]; char c[10]; float Part 2 31 32 33 106 107, ( ),, ( ), 3, int kor[5]; int eng[5]; int Microsoft Windows 4 (ANSI C2 ) int kor[5] 20 # define #define SIZE 20 int a[10]; char c[10]; float f[size]; /* 10 /* c 10 /* f 20 3 1

More information

/chroot/lib/ /chroot/etc/

/chroot/lib/ /chroot/etc/ 구축 환경 VirtualBox - Fedora 15 (kernel : 2.6.40.4-5.fc15.i686.PAE) 작동 원리 chroot유저 ssh 접속 -> 접속유저의 홈디렉토리 밑.ssh의 rc 파일 실행 -> daemonstart실행 -> daemon 작동 -> 접속 유저만의 Jail 디렉토리 생성 -> 접속 유저의.bashrc 의 chroot 명령어

More information