Linux는 실제 파일과 존재하지 않는(예: 장치) 파일을 어떻게 구별합니까?

Linux는 실제 파일과 존재하지 않는(예: 장치) 파일을 어떻게 구별합니까?

이것은 매우 낮은 수준의 질문이며 아마도 이것이 질문하기에 가장 좋은 장소가 아닐 것이라는 것을 알고 있습니다. 하지만 다른 어떤 SE 사이트보다 더 적절해 보였기에 여기까지입니다.

Linux 파일 시스템에서는 일부 파일이 실제로존재하다, 예: /usr/bin/bash존재합니다. 그러나 (내가 이해하는 한) 일부는 실제로 존재하지 않으며 더 많은 것이 존재합니다.가상다음과 같은 파일 /dev/sda: /proc/cpuinfo등 내 질문은 다음과 같습니다(두 가지이지만 별도의 질문이 되기에는 너무 밀접하게 관련되어 있습니다).

  • 읽기 명령(또는 유사한 명령)이 실행되면 Linux 커널은 이러한 파일이 실제인지(따라서 디스크에서 읽는지) 어떻게 알 수 있습니까?
  • 파일이 실제가 아닌 경우: 예를 들어 read from은 /dev/random임의의 데이터를 반환하고 read from은 /dev/null을 반환합니다 EOF. 이 가상 파일에서 읽을 데이터를 결정하는 방법(및 데이터가 가상 파일에 기록될 때 수행할 작업) - 각 파일 또는 가상 디렉터리에 적합한 별도의 읽기/쓰기에 대한 포인터가 있는 일종의 매핑이 있습니까? 스스로 주문을 하시겠습니까? 따라서 항목은 /dev/null단순히 EOF.

답변1

따라서 여기에는 기본적으로 두 가지 유형이 있습니다.

  1. 데이터와 메타데이터가 포함된 디렉터리에 익숙한 방식으로 파일을 저장하는 일반 파일 시스템(소프트 링크, 하드 링크 등 포함) 항상 그런 것은 아니지만 일반적으로 영구 저장소에 사용되는 블록 장치로 백업됩니다(tmpfs는 RAM에만 존재하지만 그 외에는 일반 파일 시스템과 동일합니다). 읽기, 쓰기, 이름 바꾸기 등의 의미는 친숙하며 모든 것이 예상대로 작동합니다.
  2. 다양한 가상 파일 시스템. /proc또는 와 같은 FUSE 사용자 정의 파일 시스템과 마찬가지로 여기에는 예가 있습니다 /sys. 실제로는 어떤 의미에서는 "사용자 정의" 의미를 가진 파일 시스템을 참조하기 때문에 훨씬 더 다양합니다. 따라서 파일 아래의 파일에서 데이터를 읽을 때 일반 파일 시스템에서와 같이 이전에 작성된 다른 항목에 의해 저장된 특정 데이터에 실제로 액세스하는 것이 아닙니다. 본질적으로 커널 호출을 수행하여 즉석에서 생성된 정보를 요청합니다. 이 코드는 의미를 구현하는 함수일 뿐이므로 원하는 것은 무엇이든 할 수 있습니다. 결과적으로 실제로는 심볼릭 링크가 아닌데 심볼릭 링크인 것처럼 가장하는 등 파일의 이상한 동작을 경험하게 됩니다.sshfsifuse/procread/proc

중요한 것은 /dev그것이 일반적으로 첫 번째라는 것입니다. 최신 배포판에서는 /devtmpfs와 같은 것을 갖는 것이 일반적이지만, 이전 시스템에서는 특별한 속성 없이 디스크의 일반 디렉터리인 것이 일반적입니다. 핵심은 다음 파일이 /devFIFO 또는 Unix 소켓과 유사한 특수 파일인 장치 노드라는 것입니다. 장치 노드에는 주요 장치 번호와 부 장치 번호가 있습니다. 이를 읽거나 쓰는 것은 커널 드라이버를 호출하는 것입니다. FIFO를 읽거나 쓰는 것은 파이프의 출력을 버퍼링하기 위해 커널을 호출하는 것과 같습니다. 드라이버는 원하는 것은 무엇이든 할 수 있지만 일반적으로 하드 드라이브에 액세스하거나 스피커에서 사운드를 재생하는 등 어떤 방식으로든 하드웨어에 닿습니다.

원래 질문에 대답하려면 다음을 수행하십시오.

  1. "파일이 존재합니까"와 관련된 두 가지 질문이 있습니다. 이는 장치 노드 파일이 실제로 존재하는지 여부와 이를 지원하는 커널 코드가 의미가 있는지 여부입니다. 전자는 일반 파일 시스템과 마찬가지로 해결됩니다. 최신 시스템은 udev하드웨어 이벤트를 모니터링하고 /dev그에 따라 장치 노드를 자동으로 생성 및 삭제하는 것과 유사한 것을 사용합니다. 그러나 이전 시스템이나 경량 사용자 지정 빌드는 미리 생성된 모든 장치 노드를 디스크에 직접 저장할 수만 있습니다. 동시에, 이러한 파일을 읽을 때 메이저 및 마이너 장치 번호에 의해 결정된 커널 코드를 호출하게 됩니다. 이것이 불합리한 경우(예를 들어 존재하지 않는 블록 장치를 읽으려고 시도하는 경우) I/O 오류입니다.

  2. 어떤 장치 파일에 대해 어떤 커널 코드를 호출할지 파악하는 방법은 다양합니다. 와 같은 가상 파일 시스템의 경우 /proc자체 기능을 구현합니다 read. write커널은 마운트 지점을 기반으로 해당 코드를 호출하고 파일 시스템 구현이 나머지를 처리합니다. 장치 파일의 경우 주 및 부 장치 번호를 기준으로 예약됩니다.

답변2

/dev/sda1다음은 거의 최신 Arch Linux 서버에 있는 파일 목록입니다.

% ls -li /dev/sda1
1294 brw-rw---- 1 root disk 8, 1 Nov  9 13:26 /dev/sda1

/dev/따라서 for의 디렉토리 항목에는 sdainode 번호 1294가 있습니다. 디스크에 있는 실제 파일입니다.

파일 크기가 일반적으로 나타나는 위치를 확인하세요. 대신 "8, 1"이 나타납니다. 이는 주요 및 보조 장치 번호입니다. 또한 파일 권한의 "b"를 참고하세요.

파일에는 /usr/include/ext2fs/ext2_fs.h다음(조각) C 구조가 포함되어 있습니다.

/*
 * Structure of an inode on the disk
 */
struct ext2_inode {
    __u16   i_mode;     /* File mode */

이 구조는 파일 inode의 디스크 구조를 보여줍니다. 구조에는 흥미로운 것들이 많이 있습니다. 자세히 살펴보세요.

i_mode16비트 이며 struct ext2_inode사용자/그룹/기타, 읽기/쓰기/실행 권한에 9비트만 사용하고 setuid, setgid 및 Sticky에 3비트만 사용합니다. "일반 파일", "링크", "디렉토리", "명명된 파이프", "유닉스 제품군 소켓" 및 "블록 장치"와 같은 유형을 구별하기 위해 4비트가 있습니다.

Linux 커널은 일반적인 디렉토리 조회 알고리즘을 따른 다음 요소의 권한 및 플래그를 기반으로 결정을 내릴 수 있습니다 i_mode. 블록 장치 파일 "b"의 경우 주 및 부 장치 번호를 찾을 수 있으며 전통적으로 주 번호는 디스크를 처리하는 일부 커널 기능(장치 드라이버)에 대한 포인터를 찾는 데 사용됩니다. 보조 장치 번호는 일반적으로 SCSI 버스 장치 번호, EIDE 장치 번호 또는 유사한 장치 번호로 사용됩니다.

파일 처리 방법에 대한 다른 결정은 /proc/cpuinfo파일 시스템 유형에 따라 결정됩니다. 다음을 수행하는 경우:

% mount | grep proc 
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)

/proc파일 시스템 유형이 "proc"임을 알 수 있습니다 . ReiserFS 또는 DOS 파일 시스템에서 파일을 열면 커널이 다른 기능을 사용하여 파일을 찾고 파일의 데이터를 찾는 것과 마찬가지로 파일에서 데이터를 읽으면 /proc커널이 파일 시스템 유형에 따라 다른 작업을 수행하게 됩니다. 문서.

답변3

결국, 그것들은 모두 유닉스 파일이고, 그것이 바로 추상화의 아름다움입니다.

커널이 파일을 처리하는 방식은 이제 다른 이야기입니다.

/proc, 이제 /dev 및 /run(일명 /var/run)은 RAM의 가상 파일 시스템입니다. /proc는 커널 변수 및 구조/창에 대한 인터페이스입니다.

"Linux 커널"을 읽어 보시기 바랍니다.http://tldp.org/LDP/tlk/tlk.html및 Linux 장치 드라이버, 제3판https://lwn.net/Kernel/LDD3/.

나는 또한 "FreeBSD 운영 체제의 설계 및 구현"을 좋아합니다.http://www.amazon.com/Design-Implementation-FreeBSD-Operating-System/dp/0321968972/ref=sr_1_1

귀하의 질문과 관련된 관련 페이지를 봅니다.

http://www.tldp.org/LDP/tlk/dd/drivers.html

답변4

파일 시스템의 모든 파일은 파일 I/O를 허용한다는 점에서 "실제"입니다. 파일을 열면 커널은 (객체 지향 프로그래밍 측면에서) 파일처럼 동작하는 객체인 파일 설명자를 생성합니다. 파일을 읽으면 파일 설명자는 읽기 메서드를 실행하고, 이 메서드는 파일 시스템(sysfs, ext4, nfs 등)에서 파일의 데이터를 요청합니다. 파일 시스템은 사용자 공간에 대한 통합 인터페이스를 제공하고 읽기 및 쓰기를 처리하는 방법을 알고 있습니다. 그러면 파일 시스템은 다른 계층에 요청을 처리하도록 요청합니다. ext4 파일 시스템의 일반 파일의 경우 파일 시스템의 데이터 구조 조회(디스크 읽기 포함)와 궁극적으로 디스크(또는 캐시)에서 읽어 데이터를 읽기 버퍼에 복사하는 작업이 포함됩니다. sysfs에 있는 파일의 경우 일반적으로 sprintf()가 버퍼에 무언가를 쓰는 것뿐입니다. 블록 개발 노드의 경우 디스크 드라이버에게 일부 블록을 읽고 이를 버퍼에 복사하도록 요청합니다(메이저 번호와 마이너 번호는 요청을 보낼 드라이버를 파일 시스템에 알려줍니다).

관련 정보