* 채용설명회
* strcut에 대한 고민
FileSystem (The Unix File System)
Unix 계열(linux)의 시스템에서 프로세스가 파일을 다룰 때 필요한 개념들.
file
- unix file system에서 파일은 논리적으로 bytes의 steam으로 볼 수 있는 데이터의 colliection로, 가장 작은 저장장치 단위이다.
- 디렉토리도, 파일도, 장치도 모두 파일! 이 개념을 잘 알아야 한다.
file descriptor
- 하나의 파일 혹은 I/O resocure(파이프나 네트워크 소켓 같은)에 대한 process-unique identifier.
- 프로세스가 어떤 파일에 접근할 때 그 파일을 구분하기 위해 사용하는 식별자라고 생각할 수 있다. 음이 아닌 정수값을 갖는데, standard하게 정해진 값으로는 0,1,2가 있다. 이들은 프로세스가 메모리에서 실행할 때 기본적으로 할당되는 FD이며 따라서 이후 FD, 3부터 할당된다.
- 프로세스가 다른 파일을 open할 때, 관리자인 커널이 FD로 사용되지 않은 가장 작은 값을 할당해준다(=OS가 정수로 된 파일 디스크립터를 할당해준다.) 이 번호는 프로세스가 open이후 열린 파일에 syscall로 접근할 때 식별자로 사용되어 그 파일을 가리킬 때 사용된다.
- FD 0: Starndard Input
- FD 1: Standard Output
- FD 2: Standard Error
file descriptor table
- 각 프로세스마다 커널에서 관리하는 파일 디스크립터 테이블(FDT)로 색인(index into a per-process)된다. 즉, 어떤 프로세스와 관련된 파일들을 이 FDT를 통해 접근할 수 있다.
- 이 FDT은 모든 프로세스에서 열린 system-wide한 파일의 테이블(file table)로 색인된다.
Buffer: Memory Buffer
Buffer?
데이터 전송시 일시적으로 데이터를 보관하는 중간 저장소로 사용되는 메모리의 영역.
왜 버퍼를 사용하는가?
I/O(입출력) 작업에서 버퍼를 자주 사용하는 이유는 데이터를 읽고 쓰는 상황에서 효율을 높이기 위해서이다. 하드디스크와 같은 대용량 저장 장치는 일정 규모 이상의 청크(중대형 크기)을 한 번에 읽고 쓸 때 가장 효율적으로 읽힌다. 왜냐하면 큰 단위로 데이터를 처리할 때 데이터 전송 시간이나 탐색 시간 등의 오버헤드를 상대적으로 줄일 수 있기 때문이다. 그러나 프로그램이나 응용프로그램 단위에서는 그보다 더 작은 데이터 조각으로 작업하며, 요구사항마다 그 크기는 달라진다. 따라서 버퍼는, 이 중간에서 하드웨어는 효율적으로 데이터를 읽고 쓸 수 있도록 데이터를 처리하면서도 응용프로그램은 그보다 더 작은 데이터 단위로 접근할 수 있도록 중간에서 데이터 손실을 방지하고, 부분적으로 접근하기 용이하게 만든다. 요약하자면, 버퍼는 데이터를 효율적으로 처리하기 위한 메커니즘으로, 입출력 작업의 성능을 최적화하고 어플리케이션의 요구에 맞출 수 있도록 한다.
C에서는 버퍼 메모리가 없다면 여러 자리 수를 변수에 저장할 때 입력한 첫 번째 숫자가 변수 내부에 바로 저장되고 나머지는 저장하기 어려워진다.
- cache buffer: 일반적으로 성증을 향상시키기 위해 사용하는, 어떤 file에게 혹은 device로부터의 쓰기/읽기 작업을 할 때 group화 시켜서 하는 것.
- helper buffer: 알고리즘을 더 쉽게 하기 위해 data를 buffer에 넣는 행위
- hardware buffer: hw의 요구조건 때문에 사용되며 hw device와 memory 간 데이터 전송에서 핵심이 된다.(i.e. C)
Buffering modes
- fully buffered: 데이터가 꽉 찼을 때 입/출력 수행
- line buffered: 개행문자를 받았을 때 입/출력을 수행
- unbuffred: 데이터 저장 낳고 곧바로 입/출력 수행
C언어에서, 키보드를 이용한 입력은 처음에는 buffer에 저장되다가 메모리에 저장된다.
PintOS의 read system call과 그 내부에서 사용되는 input_get()함수에서 볼 수 있다.
int read (int fd, void *buffer, unsigned length) {
validate_buffer(buffer, length, true);
int bytesRead = 0;
if (fd == 0) {
for (int i = 0; i < length; i++) {
char c = input_getc();
((char *)buffer)[i] = c;
bytesRead++;
if (c == '\n') break;
}
} else if (fd == 1) {
return -1;
} else {
// ...
}
return bytesRead;
}
//input.c
/* Stores keys from the keyboard and serial port. */
static struct intq buffer;
/* Retrieves a key from the input buffer.
If the buffer is empty, waits for a key to be pressed. */
uint8_t
input_getc (void) {
enum intr_level old_level;
uint8_t key;
old_level = intr_disable ();
key = intq_getc (&buffer);
serial_notify ();
intr_set_level (old_level);
return key;
}
참조 링크:
How can I write to a buffer (void pointer)?
참조하기 좋은 pdf: link
Syn-Read: 다시 thread로....
이 문제에 대한 실마리가 보였다. 저번 주 발표에서 어떤 동료가 thread 구조체의 크기에 대한 발표를 하는데 그 동료가 겪은 문제와 상황이 비슷했다. fdt(file descriptor table)을 구조체 안에 직접 넣어서, 그 크기로 영향을 받아 thread magic이 변경되어서 is_thread(t)를 통과하지 못한다는 이야기였는데, 자꾸 문제가 생기는 내 코드를 보니 thread 구조체 안에 fdt[64]로 직접 이 안에 넣고 있었다. syn 시리즈의 테스트케이스들은 동기화 테스트를 위해 동시에 여러 child를 생성하고 그 안의 파일을 read/write를 하는데 fdt table이 구조체 안에 있으면 그 크기가 계속해서 커지지 않을까? 그래서 fdt를 포인터로 바꾸니 오류가 다소 줄어들었다. 그런데도 가끔 터지는 걸 보니, 코드 내 메모리 관리에서 미세한 실수가 있는 것 같다...
/* A kernel thread or user process.
*
* Each thread structure is stored in its own 4 kB page. The
* thread structure itself sits at the very bottom of the page
* (at offset 0). The rest of the page is reserved for the
* thread's kernel stack, which grows downward from the top of
* the page (at offset 4 kB). Here's an illustration:
*
* 4 kB +---------------------------------+
* | kernel stack |
* | | |
* | | |
* | V |
* | grows downward |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* | |
* +---------------------------------+
* | magic |
* | intr_frame |
* | : |
* | : |
* | name |
* | status |
* 0 kB +---------------------------------+
*/
struct thread {
// ....
//struct file *fdt[64];
struct file** fdt; /* file descriptor table */
//...
}
'공부기록 > OS' 카테고리의 다른 글
[TIL][Project 3] Virtual Memory | Address Translation (Static/Dynamic) (0) | 2023.12.21 |
---|---|
[TIL][OS] OS review Summary: Abstractions (0) | 2023.12.20 |
[TIL][Setting] ubuntu Setting for PintOS (0) | 2023.12.18 |
[WIL / PintOS] [Project 2] System Call | others (0) | 2023.12.16 |
[WIL / PintOS] [Project 2] Argument Passing | User Memory (0) | 2023.12.15 |