# open·read·write: 파일 번호 다음에 커널이 확인하는 것

v6.6 / fs/read_write.c

사용자 프로그램은 정수 파일 디스크립터로 read를 부르지만 커널 내부에서는 열린 파일을 나타내는 struct file을 찾습니다. open은 이 연결을 만들고 read와 write는 파일의 연산 표를 통해 실제 구현으로 이어집니다. 여기서는 vfs_read 전체를 보며 권한, 사용자 버퍼, 요청 범위, 파일별 함수를 어떤 순서로 확인하는지 설명합니다.

## vfs_read

```c

ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
	ssize_t ret;

	if (!(file->f_mode & FMODE_READ))
		return -EBADF;
	if (!(file->f_mode & FMODE_CAN_READ))
		return -EINVAL;
	if (unlikely(!access_ok(buf, count)))
		return -EFAULT;

	ret = rw_verify_area(READ, file, pos, count);
	if (ret)
		return ret;
	if (count > MAX_RW_COUNT)
		count =  MAX_RW_COUNT;

	if (file->f_op->read)
		ret = file->f_op->read(file, buf, count, pos);
	else if (file->f_op->read_iter)
		ret = new_sync_read(file, buf, count, pos);
	else
		ret = -EINVAL;
	if (ret > 0) {
		fsnotify_access(file);
		add_rchar(current, ret);
	}
	inc_syscr(current);
	return ret;
}

```

### 450행

```c

ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)

```

열린 파일, 사용자 목적지 버퍼, 요청 길이와 파일 위치 포인터를 받습니다. fd 숫자를 직접 받는 함수는 아닙니다.

### 452행

```c

	ssize_t ret;

```

실제 읽은 양 또는 음수 오류를 저장합니다.

### 454행

```c

	if (!(file->f_mode & FMODE_READ))

```

이 열린 파일이 읽기 모드를 가지고 있는지 비트로 확인합니다.

### 455행

```c

		return -EBADF;

```

읽기 권한으로 열린 파일이 아니므로 잘못된 파일 디스크립터 사용이라는 -EBADF를 반환합니다.

### 456행

```c

	if (!(file->f_mode & FMODE_CAN_READ))

```

파일에 읽기 가능한 연산이 마련되어 있는지 검사합니다.

### 457행

```c

		return -EINVAL;

```

읽기 연산을 제공하지 않는 조건은 -EINVAL로 반환합니다.

### 458행

```c

	if (unlikely(!access_ok(buf, count)))

```

사용자 버퍼와 길이가 접근 가능한 주소 범위인지 검사합니다. 실제 복사 성공 보장은 아닙니다.

### 459행

```c

		return -EFAULT;

```

잘못된 사용자 주소 범위이면 -EFAULT를 반환합니다.

### 461행

```c

	ret = rw_verify_area(READ, file, pos, count);

```

읽기 방향, 파일, 위치와 길이에 대해 VFS의 공통 범위·보안 검사를 수행합니다.

### 462행

```c

	if (ret)

```

검사에서 오류가 나왔는지 확인합니다.

### 463행

```c

		return ret;

```

검사 오류를 그대로 반환하고 파일 읽기를 실행하지 않습니다.

### 464행

```c

	if (count > MAX_RW_COUNT)

```

한 번의 읽기에 허용하는 최대 크기를 초과하는지 확인합니다.

### 465행

```c

		count =  MAX_RW_COUNT;

```

처리할 요청 크기를 MAX_RW_COUNT로 제한합니다. 나머지는 호출자가 후속 읽기로 처리할 수 있습니다.

### 467행

```c

	if (file->f_op->read)

```

이 파일이 전통적인 read 콜백을 제공하는지 먼저 확인합니다.

### 468행

```c

		ret = file->f_op->read(file, buf, count, pos);

```

파일별 read 구현에 동일한 파일·사용자 버퍼·길이·위치를 넘깁니다.

### 469행

```c

	else if (file->f_op->read_iter)

```

read가 없으면 반복자 기반 read_iter 구현이 있는지 확인합니다.

### 470행

```c

		ret = new_sync_read(file, buf, count, pos);

```

동기식 read 요청을 반복자 기반 호출로 구성해 실행합니다.

### 471행

```c

	else

```

두 가지 읽기 구현을 모두 제공하지 않는 경우입니다.

### 472행

```c

		ret = -EINVAL;

```

적합한 연산이 없으므로 오류를 결과로 지정합니다.

### 473행

```c

	if (ret > 0) {

```

실제로 양수 바이트를 읽은 경우에만 데이터 접근 관련 후처리를 합니다.

### 474행

```c

		fsnotify_access(file);

```

파일 접근 감시자에게 읽기 사실을 알립니다.

### 475행

```c

		add_rchar(current, ret);

```

현재 태스크의 읽은 문자·바이트 계측에 실제 반환량을 더합니다.

### 477행

```c

	inc_syscr(current);

```

이 경로의 읽기 호출 횟수 계측을 늘립니다. 실제 읽은 바이트 계수와는 다릅니다.

### 478행

```c

	return ret;

```

파일 구현의 결과 또는 검증 오류를 호출자에게 반환합니다.

