시스템 호출에서 파일 설명자 사용 [닫기]

시스템 호출에서 파일 설명자 사용 [닫기]

시스템 호출에서 파일 설명자를 사용하고 싶다고 가정해 보겠습니다(fd 번호는 매개변수를 통해 제공됩니다). 사용자 공간 프로그램이 이 시스템 호출을 사용하면 어떻게 되나요? OS는 이 특정 fd를 어디에서 찾습니까? 현재 프로세스의 파일 설명자에 있나요? 아니면 다른 곳에 있나요?

아래에서는 이 점을 설명하려고 합니다.

+--------------+     +----++--------------+
| Kernel space |     | fd ||  User space  |
|              |     |list||              |
|   handler <---------------- syscall(fd) |
|              |     |    ||              |
+--------------+     +----++--------------+

답변1

파일 디스크립터는 특정 프로세스에서 열린 모든 파일 중 하나의 파일을 참조하는 정수입니다. 일반적으로 이는 파일 설명자를 테이블에 대한 인덱스로 처리하여 커널에 의해 수행됩니다.

내 대답의 나머지 부분은 Linux에 적용됩니다.

Linux에서 각 유효한 파일 설명자는 와 연결됩니다 struct file. 이 구조에는 inode(파일의 데이터 및 메타데이터)에 대한 포인터, 파일에서 프로세스의 현재 위치, 작업 목록(실제로는 파일이 있는 파일에 대한 포인터)이 포함되어 있습니다. 파일이 위치함) 시스템에 의해 구현된 기능에 대한 포인터) 등

file파일 설명자에서 구조를 얻으려면 Linux 커널이 다음과 같이 진행됩니다. 여기서는 시스템 호출을 예로 들겠습니다 read.

SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
    struct fd f = fdget_pos(fd);
    ssize_t ret = -EBADF;

    if (f.file) {
        loff_t pos = file_pos_read(f.file);
        ret = vfs_read(f.file, buf, count, &pos);
        if (ret >= 0)
            file_pos_write(f.file, pos);
        fdput_pos(f);
    }
    return ret;
}

첫 번째 작업은 fdget_pos사용자 공간의 호출자로부터 파일 설명자를 매개변수로 가져와 다음과 같이 정의된 file파일을 반환합니다.struct fd

struct fd {
    struct file *file;
    unsigned int flags;
};

이것은 기본적으로 struct file구조를 다시 넣을 때 필요한 작업을 기억하는 몇 가지 플래그가 있는 하나입니다.

자, fdget_pos그것이 어떻게 작동하는지. 실제로는 이상한 방식으로 복잡하지만 두 가지 기본 작업으로 요약됩니다(단순화를 위해 여기서는 더 많은 확인 사항을 표시하지 않습니다).

첫 번째는 프로세스의 파일 테이블을 가져오는 것입니다. 테이블은 호출자의 프로세스 구조에 있는 포인터를 통해 사용할 수 있습니다(다음을 통해 액세스 가능) current.

struct files_struct *files = current->files;

다음 작업에는 파일 설명자의 유효성을 확인하는 작업이 포함됩니다.

if (fd < files->fdt->max_fds) // first of all, if the file descriptor is too big, then it cannot be valid
    return files->fdt->fd[fd]; // otherwise, we return the pointer stored in the table of file descriptors (may be NULL)
return NULL;

이 포인터는 함수가 반환되기 전에 제거될 수 있습니다(예를 들어 프로세스의 한 스레드가 read동일한 파일 설명자에서 동시에 다른 스레드를 실행하는 경우). close커널은 이 문제를 처리하는 역할을 담당합니다.

struct file반환된 포인터가 fdget_pos이면 시스템 NULL호출에 전달된 파일 설명자가 유효하지 않음을 의미합니다. 이 경우 시스템 호출은 오류 코드 EBADF("잘못된 파일 설명자")를 반환합니다.

요약하자면, 파일 설명자는 각 프로세스의 파일 설명자 테이블에 대한 색인일 뿐입니다. 그러나 단순히 역참조하는 것만으로는 충분하지 않습니다 NULL. 왜냐하면 파일 테이블의 항목은 .

관련 정보