Semaphore
- "generalized lock"으로서, non-negative integer value를 가지며 두 가지 연산을 지원
P() or down()
: 양수가 되기를 기다리다가, 양수가 되면 1 감소
V() or up()
: 세마포어를 1 증가시키고 기다리는 P를 깨움
- mutual exclusion으로 사용하려면,
initial value = 1 semaphore.down(); // critical section semaphore.up();
- signaling other threads
initial value = 0 ThreadJoin { semaphore.down(); }
Process(cont'd)
exec
wait
: tcpid = wait(&status)
와 같이 쓰게 되면, parent process가 child process의 종료를 기다린다. status는 child process에서 exit(42)
와 같이 종료하면서 반환한 코드값이다.
sigaction
: signaling은 프로세스 간 소통하는 방법이다.
File
- Unix/POSIX에서는 모든 것을 "파일"로 취급한다(디스크상의 파일, 외부 device, 네트워크, interprocess communication 등)
- uniformity: everything is a file
- open before use
- byte-oriented
- kernel buffered reads
- kernel buffered writes
- explicit close
- system call
open(), read(), write(), close()
사용
- 모든 process는 CWD(current working directory)가 있다.
int chdir(const char *path)
로 바꿀 수 있음
- 절대경로는 CWD를 무시하고, 상대경로는 CWD를 기준으로 한다
Streams(high-level)
- unformatted sequences of bytes with a position
FILE *fopen (const char *filename, const char *mode)
- FILE 자료구조에 대한 포인터를 반환함(에러가 날 경우 NULL pointer)
- stdio.h
- stdin, stdout, stderr는 프로그램이 실행될 때 implicitly 실행됨
File Descriptor(low-level)
int open (const char *filename, int flags[, mode_t mode])
int creat (const char *filename, mode_t mode)
int close (int filedes)
- open에서 반환되는 것이 file descriptor다.
- 에러의 경우 음수값이 반환되며, global variable인
errno
에 에러 관련 내용이 set된다
- file description object는 열려있는 파일이 되며, 보안을 위해 포인터를 주는 대신 integer를 주는 것이다.
STDIN_FILENO
STDOUT_FILENO
STDERR_FILENO
int fileno (FILE _stream) // file descriptor 확인
FILE* fdopen(int filedes, const char* opentype) // 파일에 대한 포인터 확인
ssize_t read(int filedes, void *buffer, size_t maxsize) // 최대 maxsize 바이트까지 읽으며, 읽은 바이트 수를 반환한다
// 0이 반환되면 EOF, -1이 반환되면 에러
ssize_t write(int filedes, const void *buffer, size_t size)
off_t lseek (int filedes, off_t offset, int whence)
- duplicating(
int dup2
, int dup
), pipe(int pipe(int pipefd[2])
), file locking, memory-mapping, asynchronous I/O 등
High-level vs. Low-level
fread
는 system call 이외에도 여러 가지 다른 작업(e.g. buffer)을 수행하지만, read
는 system call에 대한 wrapper와 같다.
FILE
에는 file descriptor, buffer, lock 등이 함께 담겨있다.
- 그래서
fwrite
를 하게 되면 일단 buffer에 쓰인 뒤에 가득 차야 flush된다.(혹은 C가 알아서 어떤 시점에 flush할 수도 있다)
fflush
를 필요한 시점에 사용해야 하고, fclose
를 통해 파일을 닫고 buffer를 flush 후 메모리에서 해제할 수 있다.
- buffer를 사용하는 이유는, syscall은 function call 대비 훨씬 느리기 때문이다. 한번의 syscall로 많은 양을 미리 user의 buffer에 가져와 놓고 사용한다.
Open File Description
- 파일을 열게 되면 kernel 영역 내에서 open file description이 생기고, file descriptor가 이를 가리킨다. 그래서
fork()
로 프로세스를 만들게 되면 이 모든 것이 복사되어 공유된다.
```
댓글