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


28

이것은 다소 낮은 수준의 질문이며 질문하기 가장 좋은 곳이 아닐 수도 있음을 이해합니다. 그러나 다른 SE 사이트보다 더 적절 해 보였습니다.

나는 리눅스 파일 시스템에 일부 파일이 실제로 알고 있을 예를 들어, : /usr/bin/bash존재입니다. 그러나, (지금까지의 내가 그것을 이해), 일부는 실제로 더 같은 존재입니다하지 않는 가상 파일을, 예를 들면 : /dev/sda, /proc/cpuinfo, 등 내 질문이 있습니다 (그들은 두 가지,하지만 너무 밀접하게 별도의 질문으로 관련) :

  • read 명령 (또는 그와 같은)이 발행 될 때 Linux 커널은 이러한 파일이 실제 파일인지 디스크에서 읽는지 여부를 어떻게 알 수 있습니까?
  • 파일이 실제가 아닌 경우 : 예를 들어, from from /dev/random은 임의의 데이터를 반환하고 read from /dev/null은을 반환 EOF합니다. 이 가상 파일에서 읽을 데이터 (및 가상 파일에 데이터를 쓸 때 / 경우에도 수행 할 작업)를 어떻게 해결합니까?-각 파일에 적합한 읽기 / 쓰기 명령을 분리하기위한 포인터가있는지도 또는 가상 디렉터리 자체에 대해서도? 따라서에 대한 항목 /dev/null은 단순히을 반환 할 수 EOF있습니다.

1
파일이 작성되면 커널은 해당 유형을 기록합니다. 그런 다음 일반 디스크 파일은 심볼릭 링크, 블록 장치, 문자 장치, 디렉토리, 소켓, FIFO 등과 다르게 처리됩니다. 알아 두어야 할 것은 커널의 작업입니다.
Jonathan Leffler

mknod에 대한 남자 pge 참조
Jasen

이것은 "전등 스위치가 전등이 켜져 있는지 어떻게 알 수 있습니까?"라고 묻는 것과 같습니다. 전등 스위치는 전등의 점등 여부를 결정합니다.
Monica와의 가벼운 경주

답변:


25

기본적으로 두 가지 유형이 있습니다.

  1. 데이터 및 메타 데이터가있는 디렉토리에 파일을 보유하는 일반 파일 시스템 (소프트 링크, 하드 링크 등). 이들은 영구 저장을 위해 블록 장치에 의해 지원되는 경우가 많지만 항상 그런 것은 아닙니다 (tmpfs는 RAM에만 있지만 일반적인 파일 시스템과 동일합니다). 이것들의 의미는 친숙하다. 읽기, 쓰기, 이름 바꾸기 등 모든 것이 예상대로 작동합니다.
  2. 다양한 종류의 가상 파일 시스템. /proc/sys예는 FUSE 사용자 정의 파일 시스템처럼, 여기 sshfsifuse. 이것들은 훨씬 더 다양합니다. 왜냐하면 실제로는 의미가 '사용자 정의'인 시맨틱을 가진 파일 시스템을 참조하기 때문입니다. 따라서에서 파일을 읽을 때 /proc실제로는 일반 파일 시스템에서와 같이 이전에 다른 것에 의해 저장된 특정 데이터에 액세스하지 않습니다. 본질적으로 커널 호출을 수행하여 즉시 생성되는 정보를 요청합니다. 그리고이 코드는 read의미를 구현하는 어딘가에 있기 때문에 좋아하는 모든 것을 할 수 있습니다 . 따라서 파일이 이상한 /proc경우 심볼릭 링크 인 것처럼 아래의 파일에서 이상한 동작을합니다.

열쇠는 /dev실제로는 일반적으로 첫 번째 종류 중 하나입니다. 현대 배포판 /dev에서는 tmpfs와 같은 것이 일반적이지만, 구형 시스템에서는 특별한 속성없이 디스크의 일반 디렉토리가되는 것이 일반적입니다. 핵심은 아래 /dev파일이 FIFO 또는 Unix 소켓과 유사한 특수 파일 유형 인 장치 노드라는 것입니다. 디바이스 노드에는 주 번호와 부 번호가 있으며, FIFO를 읽거나 쓰는 것이 커널에서 출력을 파이프에 버퍼링하기 위해 호출하는 것과 마찬가지로, 읽거나 쓰는 것이 커널 드라이버를 호출하는 것입니다. 이 드라이버는 원하는 작업을 수행 할 수 있지만 일반적으로 하드 디스크에 액세스하거나 스피커에서 사운드를 재생하는 등 하드웨어에 영향을줍니다.

원래 질문에 대답하려면 :

  1. '파일이 있는지 여부'와 관련된 두 가지 질문이 있습니다. 이것들은 장치 노드 파일이 문자 그대로 존재하는지 여부와 그것을 뒷받침하는 커널 코드가 의미가 있는지 여부입니다. 전자는 일반 파일 시스템에서와 마찬가지로 해결됩니다. 최신 시스템 udev은 하드웨어 이벤트를 감시하고 /dev그에 따라 장치 노드를 자동으로 생성 및 파괴하는 데 사용 됩니다. 그러나 오래된 시스템 또는 간단한 사용자 지정 빌드는 모든 장치 노드를 문자 그대로 디스크에 담아 미리 만들 수 있습니다. 한편,이 파일들을 읽을 때, 주요 및 부 장치 번호에 의해 결정되는 커널 코드를 호출하고 있습니다. 이것이 합리적이지 않으면 (예를 들어 존재하지 않는 블록 장치를 읽으려고 시도하는 경우) 일종의 I / O 오류가 발생합니다.

  2. 어떤 장치 파일에 대해 어떤 커널 코드를 호출해야하는지 알아내는 방법. 와 같은 가상 파일 시스템 /proc의 경우 자체 readwrite기능 을 구현 합니다. 커널은 마운트 지점에 따라 해당 코드를 호출하고 파일 시스템 구현이 나머지를 처리합니다. 장치 파일의 경우 주 장치 번호와 부 장치 번호에 따라 전달됩니다.


예를 들어, 오래된 시스템의 전원을 끈 경우 파일 /dev이 여전히있을 수 있지만 시스템을 시작할 때 파일이 지워지는 것 같습니다.
Joe

2
기존 시스템 (동적 장치 작성이없는 시스템)이 정상적으로 또는 비정상적으로 종료 된 경우 장치 노드는 파일과 마찬가지로 디스크에 남아 있습니다. 그런 다음 다음에 부팅 할 때 디스크에도 남게되므로 정상적으로 사용할 수 있습니다. 현대 시스템에서만 장치 노드를 만들고 파괴하는 특별한 일이 발생합니다.
Tom Hunt

따라서 최신 시스템을 사용하지 않으면 tmpfs필요에 따라 동적으로 시스템을 생성 및 삭제할 수 있습니다 (예 : 부팅 및 종료?
Joe

3
devtmpfs, /dev현대 리눅스 의 파일 시스템은와 비슷 tmpfs하지만 지원에 약간의 차이가 udev있습니다. 커널은 udev부팅을 덜 복잡하게하기 위해으로 넘기기 전에 자체 자동화 된 노드 생성을 수행합니다 . 이러한 모든 경우에 장치 노드는 RAM에만 존재하며 하드웨어에 따라 동적으로 생성 및 파괴됩니다. 아마 당신은 udev평범한 on-disk 에서도 사용할 수 /dev있지만, 나는 이것을 한 적이 없으며 좋은 이유가없는 것 같습니다.
Tom Hunt

17

다음은 /dev/sda1최신 Arch Linux 서버에 대한 파일 목록입니다 .

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

의 디렉토리 엔트리 그래서 /dev/에 대한이 sda아이 노드 번호를 가지고, 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_mode요소 struct ext2_inode는 16 비트이며 사용자 / 그룹 / 기타, 읽기 / 쓰기 / 실행 권한에는 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"인 것을 알 수 있습니다 . /procReiserFS 또는 DOS 파일 시스템에서 파일을 열면 커널이 다른 기능을 사용하여 파일을 찾고 데이터를 찾는 것처럼 파일에서 파일을 읽으면 커널이 파일 시스템 유형에 따라 다른 작업을 수행합니다 파일.


"디스크의 실제 파일"에만 inode 번호가 표시되어 있습니까? 내가 얻을 4026531975 -r--r--r-- 1 root root 0 Nov 14 18:41 /proc/mdstat분명히 "실제 파일"하지 않은.
guntbert

7

마지막 날에는 Unix의 모든 파일입니다. 그것은 추상화의 아름다움입니다.

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

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

Linux Kernel http://tldp.org/LDP/tlk/tlk.html 및 Linux Device Drivers, Third Edition 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


고마워, 나는 당신이 그 말을 한 후에 첫 번째 질문을 약간 바꿨습니다.
Joe

마지막 코멘트를 읽으십시오.
Rui F Ribeiro

5

@RuiFRibeiro와 @BruceEdiger의 답변 외에도, 여러분이 만드는 차이점은 커널이 만드는 차이점이 아닙니다. 사실, 당신은 일반 파일, 디렉토리, 심볼릭 링크, 장치, 소켓 등 다양한 종류의 파일을 가지고 있습니다. 파일 형식에 대한 정보는 다음과 같이 가질 수 있습니다 ls. 줄의 첫 번째 문자입니다. 예를 들면 다음과 같습니다.

$ls -la /dev/sda
brw-rw---- 1 root disk 8, 0 17 nov.  08:29 /dev/sda

맨 처음 'b'는이 파일이 블록 장치임을 나타냅니다. 대시는 일반 파일, 'l'기호 링크 등을 의미합니다. 이 정보는 파일의 메타 데이터에 저장되며 stat예를 들어 시스템 호출 을 통해 액세스 할 수 있으므로 커널은 예를 들어 파일과 기호 링크를 다르게 읽을 수 있습니다.

그런 다음 "실제 파일" /bin/bash과 "가상 파일"을 구별 /proc/cpuinfo하지만 ls둘 다 일반 파일로보고하므로 차이점은 다른 종류입니다.

ls -la /proc/cpuinfo /bin/bash
-rwxr-xr-x 1 root root  829792 24 août  10:58 /bin/bash
-r--r--r-- 1 root wheel      0 20 nov.  16:50 /proc/cpuinfo

결과는 다른 파일 시스템에 속한다는 것입니다. /proc의사 파일 시스템의 마운트 지점 procfs이지만 /bin/bash일반 디스크 파일 시스템에 있습니다. Linux가 파일을 열면 (파일 시스템에 따라 다르게 수행됨) file다른 속성 중에서도이 파일을 사용하는 방법을 설명하는 여러 함수 포인터의 구조 를 갖는 데이터 구조 를 채 웁니다 . 따라서 다른 종류의 파일에 대해 고유 한 동작을 구현할 수 있습니다.

예를 들어, 다음에 의해 광고되는 작업입니다 /proc/meminfo.

static int meminfo_proc_open(struct inode *inode, struct file *file)
{
    return single_open(file, meminfo_proc_show, NULL);
}

static const struct file_operations meminfo_proc_fops = {
    .open       = meminfo_proc_open,
    .read       = seq_read,
    .llseek     = seq_lseek,
    .release    = single_release,
};

의 정의를 보면 meminfo_proc_open이 함수가 함수에 의해 반환 된 정보로 메모리의 버퍼를 채우는 것을 알 수 있습니다.이 함수 meminfo_proc_show는 메모리 사용에 대한 데이터를 수집하는 작업입니다. 그런 다음이 정보를 정상적으로 읽을 수 있습니다. 파일을 열 때마다 함수 meminfo_proc_open가 호출되고 메모리에 대한 정보가 새로 고쳐집니다.


3

파일 시스템의 모든 파일은 파일 I / O를 허용한다는 의미에서 "실제"입니다. 파일을 열면 커널은 파일처럼 작동하는 객체 (객체 지향 프로그래밍의 의미) 인 파일 디스크립터를 만듭니다. 파일을 읽는 경우 파일 디스크립터는 read 메소드를 실행하여 파일 시스템 (sysfs, ext4, nfs 등)에 파일의 데이터를 요청합니다. 파일 시스템은 사용자 공간에 균일 한 인터페이스를 제공하며 읽기 및 쓰기를 처리하기 위해 수행 할 작업을 알고 있습니다. 파일 시스템은 다른 계층에 요청을 처리하도록 요청합니다. ext4 파일 시스템과 같은 일반 파일의 경우 파일 시스템의 데이터 구조 (디스크 읽기가 필요할 수 있음)를 조회하고 결국 디스크 (또는 캐시)에서 데이터를 읽기 버퍼에 복사하기위한 읽기가 필요합니다. sysfs 파일의 경우 일반적으로 버퍼에 무언가를 sprintf ()합니다. 블록 개발 노드의 경우 디스크 드라이버에게 일부 블록을 읽고이를 버퍼에 복사하도록 요청합니다 (주요 및 부수는 파일 시스템에 요청하는 드라이버를 알려줍니다).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.