왜 / dev / null이 파일입니까? 왜 그 기능이 간단한 프로그램으로 구현되지 않습니까?


114

Linux의 특수 파일 개념을 이해하려고합니다. 그러나 특수 파일 /dev을 C에있는 몇 줄로 구현할 수있을 때 어리석은 것처럼 보입니다.

또한 null로 리디렉션하는 대신 파이핑하는 것과 거의 같은 방식으로 사용할 수 있습니다 /dev/null. 파일로 사용하는 특별한 이유가 있습니까? 파일을 파일로 만들지 않으면 같은 파일에 너무 많은 프로그램에 액세스하는 등 다른 많은 문제가 발생합니까?


20
왜 덧붙여, 이러한 오버 헤드의 대부분은 또한 cat foo | bar보다 (규모) 훨씬 더 나쁘다 bar <foo. cat사소한 프로그램이지만 사소한 프로그램조차도 비용을 발생시킵니다 (일부 FIFO 시맨틱에 특정)-프로그램이 seek()FIFO 내부에 있을 수 없으므로 , 예를 들어 탐색으로 효율적으로 구현할 수있는 프로그램은 훨씬 더 비싼 작업을 수행 할 수 있기 때문에 파이프 라인이 주어 졌을 때, 캐릭터 디바이스를 사용 /dev/null하면 그러한 조작을 위조하거나 실제 파일을 사용하여이를 구현할 수 있지만 FIFO는 컨텍스트 인식을 처리 할 수 ​​없습니다).
Charles Duffy

13
grep blablubb file.txt 2>/dev/null && dosomething프로그램 또는 함수 인 null과 함께 작동 할 수 없습니다.
rexkogitans

16
계획 9 운영 체제에 대해 읽어 보면 "모든 것이 파일"이라는 비전이 어디로 가고 있는지 알아볼 수 있습니다. 리소스를 파일로 사용할 수있는 힘을 좀 더 쉽게 볼 수 있습니다. 일단 현대 리눅스 / 유닉스처럼 대부분 / 부분적으로가 아니라 개념을 완전히 수용하는 시스템을 본다면
mtraceur

25
뿐만 아니라 아무도 커널 공간에서 실행되는 장치 드라이버가 있음을 지적하지 않기 때문에 이다 "C 라인의 소수"와 프로그램 , 답변 중 어느 것도 지금까지 실제로 "같은 파일에 액세스 너무 많은 프로그램"의 상상을 해결 없었다 질문에.
JdeBP

12
당신은 그것을 믿지 않을 것 있지만 : 다시 "그 기능은 C에서 라인의 소수에 의해 구현 될 수있다" 되는 C의 행의 소수에 의해 구현! 예를 들어, read함수 의 본문은 /dev/null"return 0"으로 구성됩니다 (이것은 아무것도하지 않으며 EOF가 발생 함을 의미합니다). (정적 github.com/torvalds/linux/blob/master/ drivers / char / mem.c ) ssize_t read_null(struct file *file, char __user *buf, size_t count, loff_t *ppos) { return 0; }(아, @JdeBP가 이미 그 점을 지적했음을 알 수 있습니다. 어쨌든, 여기에 그림이 있습니다 :-).
피터 A. 슈나이더

답변:


153

캐릭터 전용 장치를 사용함으로써 얻을 수있는 성능 이점 외에도 주요 이점은 모듈성 입니다. / dev / null은 셸 파이프 라인뿐만 아니라 파일이 필요한 거의 모든 컨텍스트에서 사용될 수 있습니다. 파일을 명령 행 매개 변수로 승인하는 프로그램을 고려하십시오.

# We don't care about log output.
$ frobify --log-file=/dev/null

# We are not interested in the compiled binary, just seeing if there are errors.
$ gcc foo.c -o /dev/null  || echo "foo.c does not compile!".

# Easy way to force an empty list of exceptions.
$ start_firewall --exception_list=/dev/null

프로그램을 소스 또는 싱크로 사용하는 것이 매우 번거로운 경우입니다. 쉘 파이프 라인의 경우에도 stdout과 stderr는 독립적으로 파일로 리디렉션 될 수 있습니다.

# Suppress errors, but print output.
$ grep foo * 2>/dev/null

14
또한 /dev/null쉘 명령에서만 사용하지 마십시오 . 소프트웨어에 제공된 다른 매개 변수 (예 : 구성 파일)에서이 매개 변수를 사용할 수 있습니다. --- 소프트웨어를 포트하는 것이 매우 편리합니다. /dev/null일반 파일과 차이를 만들 필요는 없습니다 .
pabouk

실행 파일을 싱크하기위한 별도의 리디렉션에 대한 부분을 이해하기가 어렵습니다. C에서는 연결을 설정 하는 호출을 변경하여 다른 프로세스 배관 과 마찬가지로 pipe,을 수행 합니까? 그것은 우리가 너무 많은 장치와 같은 파일 패턴을 가지고 있지 않았고에서 일 대부분의 경우 대부분의 포탄하지만 아마도, 그렇게 할 수있는 예쁜 방법을 제공하지 않는 사실 및 실행 파일로 취급하고, 껍질이 방법으로 설계되었을 것입니다 지금 리디렉션하는 것처럼 쉽게 할 수 있습니다. forkexecvedup2/dev/proc
aschepler

6
@aschepler 싱크 실행 파일로 리디렉션하지 않는 것은 어렵습니다. 널 싱크가 파일이 아닌 경우 두 파일 널 싱크 에서 쓰거나 읽을 수있는 응용 프로그램을 작성하는 것이 더 복잡합니다. 모든 것이 파일이 아닌 세상에 대해 이야기하지 않는 한 모든 것이 실행 가능한가? * nix OS와는 매우 다른 모델입니다.
큐빅

1
@aschepler 잊어 버렸습니다 wait4! POSIX api를 사용하여 stdout과 stderr을 다른 프로그램으로 파이프하는 것이 가능하며 stdout과 stderr을 다른 명령으로 리디렉션하기위한 영리한 쉘 구문을 발명 할 수 있습니다. 그러나 지금은 그러한 쉘을 알지 못합니다. 더 큰 요점은 / dev / null이 기존 도구 (파일과 함께 작동하는)에 깔끔하게 맞고 / bin / null은 그렇지 않다는 것입니다. 우리는 또한 gcc가 파일처럼 프로그램으로 출력을 쉽게 (안전하게!) 만드는 IO API를 상상할 수있다. 그러나 그것은 우리가 처한 상황이 아니다.
ioctl

2
껍질에 관한 @ioctl; 등의 작업을 수행 할 수있게됩니다 적어도 zsh을하고 bash는 모두 grep localhost /dev/ /etc/hosts 2> >(sed 's/^/STDERR:/' > errfile ) > >(sed 's/^/STDOUT:/' > outfile)별도로 처리 결과적 errfileoutfile
마티 Nalis을

62

공평하게, 그것은 그 자체 로 정규 파일 이 아닙니다 . 그것은 문자 특수 장치입니다 :

$ file /dev/null
/dev/null: character special (3/2)

파일이나 프로그램이 아닌 장치로 작동한다는 것은 입력 / 출력을 표준 입력 / 출력 / 오류를 포함한 모든 파일 디스크립터에 첨부 할 수 있으므로 입력 또는 출력을 리디렉션하는 작업이 더 간단하다는 것을 의미합니다.


24
cat file | null파이프를 설정하고, 프로세스를 생성하고, 새로운 프로세스에서 "널 (null)"을 실행하는 등 많은 오버 헤드가 발생합니다. 또한 null자체적으로 버퍼에 바이트를 읽는 루프에서 꽤 많은 CPU를 그냥 버렸다 ... /dev/null커널에서 구현하는 것이 더 효율적이다. 또한 /dev/null리디렉션 대신 인수 로 전달하려면 어떻게해야 합니까? (당신은 <(...)bash에서 사용할 수 있지만 훨씬 더 무거운 방법입니다!)
filbranden

4
null리디렉션을 사용하는 대신 이름이 지정된 프로그램으로 파이프 /dev/null해야하는 경우, stderr 만 null로 보내면서 프로그램을 실행하도록 쉘에 간단하고 명확한 방법이 있습니까?
Mark Plotnick

5
이것은 오버 헤드 데모를위한 정말 비싼 설정입니다. /dev/zero대신 사용 하는 것이 좋습니다 .
chrylis

20
그 예는 잘못되었습니다. dd of=-이라는 파일 에 쓰려면 기본적으로 쓰는 위치이므로 stdout에 쓰려면 -생략하십시오 . stdin을 읽지 못하는 것처럼 파이프가 작동 하지 않으므로 SIGPIPE로 종료됩니다. 입력을 버리는 명령에 대해서는 ...을 사용할 수 있습니다 . 또한 병목과 관련이없는 비교는 아마도 난수 생성 일 것입니다. of=ddfalsefalseddcat > /dev/null
Stéphane Chazelas

8
AST 버전 dd등은 대상이 / dev / null임을 감지했을 때 쓰기 시스템 호출을 방해하지 않습니다.
Mark Plotnick

54

유닉스 (그리고 결과적으로 리눅스)를 형성 한 비전 / 디자인과 많은 관련이있는 이유 와 그로 인한 장점을 의심합니다 .

의심 할 여지없이 여분의 프로세스를 시작하지 않으면 무시할 수없는 성능상의 이점이 있지만 더 많은 것으로 생각됩니다. Early Unix는 "모든 것이 파일입니다"라는 은유를 가지고 있습니다. 쉘 스크립팅 관점이 아니라 시스템 관점에서 볼 수 있습니다.

null명령 행 프로그램과 /dev/null장치 노드 가 있다고 가정 하십시오. 쉘 스크립팅의 관점에서 foo | null프로그램은 실제로 진정입니다 유용 하고 편리 하고, foo >/dev/null입력 작은 조금 오래 걸리고 이상하게 보일 수있다.

그러나 두 가지 연습이 있습니다.

  1. null기존 유닉스 도구를 사용하여 /dev/null쉽게 프로그램 을 구현해 봅시다 : cat >/dev/null. 끝난.

  2. 당신 /dev/null은 측면에서 구현할 수 있습니까 null?

입력을 버리는 C 코드가 사소한 것이므로 타스크에 가상 파일을 제공하는 것이 유용한 아직 명확하지 않을 수 있습니다.

고려해보십시오 : 거의 모든 프로그래밍 언어 는 파일, 파일 디스크립터 및 파일 경로와 함께 작동 해야합니다. Unix의 "모든 것이 파일"패러다임의 일부이기 때문입니다.

stdout에 쓰는 프로그램 만 있으면 모든 쓰기를 삼키는 가상 파일이나 파이프를 모든 쓰기를 삼키는 프로그램으로 파이프를 재지 정하는 것은 문제가되지 않습니다.

이제 데이터를 읽거나 쓰는 데 파일 경로를 사용하는 프로그램 (대부분의 프로그램)이 있고 해당 프로그램에 "공백 입력"또는 "이 출력 폐기"기능을 추가하려는 /dev/null경우 무료로 제공됩니다.

그것의 우아함은 모든 관련 프로그램의 코드 복잡성을 줄이는 것입니다-시스템이 실제 "파일 이름"을 가진 "파일"로 제공 할 수있는 일반적인 일반적인 사용 사례마다 코드가 사용자 정의 명령을 추가하지 않아도됩니다 처리 할 라인 옵션 및 사용자 정의 코드 경로.

좋은 소프트웨어 엔지니어링은 종종 생각하기 쉬워 지지만 유연하게 유지 되는 방식으로 문제의 일부 요소를 추상화하기위한 좋은 또는 "자연적인"은유를 찾는 데 의존 하기 때문에 기본적으로 동일한 수준의 상위 수준 문제를 해결할 필요가 없습니다. 동일한 하위 수준의 문제에 대한 솔루션을 지속적으로 다시 구현하는 데 시간과 정신 에너지를 소비합니다.

자원에 액세스하기위한 하나의 은유 것 같다 "모든 파일입니다"당신은 호출 open객체에 대한 참조 (파일 기술자)를 받고하는 계층 구조로 네임 스페이스에 지정된 경로로, 당신은 할 수 readwrite파일 설명에 등. stdin / stdout / stderr은 방금 미리 열린 파일 설명자입니다. 파이프는 파일과 파일 설명 자일 뿐이며 파일 리디렉션을 사용하면 이러한 모든 부분을 서로 붙일 수 있습니다.

유닉스는 이러한 추상화가 얼마나 잘 작동했는지에 따라 부분적으로 성공했으며 /dev/null그 전체의 일부로 가장 잘 이해됩니다.


추신 : "모든 것이 파일입니다"라는 유닉스 버전 /dev/null과 그 뒤에 나오는 많은 시스템에서 구현 된 은유의보다 유연하고 강력한 일반화를 향한 첫 단계 와 같은 것들을 살펴볼 가치가 있습니다.

예를 들어, 유닉스에서 특별한 파일과 같은 객체 /dev/null는 커널 자체에서 구현되어야했지만, 그 이후로 프로그램을위한 방법을 제공하는 여러 시스템이 만들어진 파일 / 폴더 형태로 기능을 노출하는 것이 유용하다는 것이 밝혀졌습니다 하기 위해서.

첫 번째는 Unix를 만든 동일한 사람들이 만든 Plan 9 운영 체제였습니다. 나중에 GNU Hurd는 "번역자"와 비슷한 일을했습니다. 한편 리눅스는 결국 FUSE (다른 주류 시스템에도 확산 됨)를 얻었습니다.


8
@PeterCordes는 디자인을 이해하지 못하는 위치에서 출발합니다. 모두가 이미 디자인을 이해했다면이 질문은 존재하지 않을 것입니다.
OrangeDog

1
@ mtraceur : 루트 권한없이 이미지 파일을 마운트 하시겠습니까? 퓨즈에 루트가 필요하지 않을 수도 있지만 확실하지 않습니다.
Peter Cordes

1
@PeterCordes RE : "이상한 것으로 보임": 디자인에 대한 사과가 아니며, 시스템 구현에 대해 생각하지 않고 시스템에 대한 유레카 순간을 보지 못한 경우 어떻게 보일지에 대한 인정입니다. 넓은 디자인 이점. 나는 "쉘 스크립팅 관점에서"로 문장을 열고, 몇 문장 전에 시스템 관점과 시스템 관점의 대조를 암시함으로써 그것을 명확하게하려고 노력했다. 더 이상 생각하면 "이상하게 보일 수 있습니다"가 더 낫습니다. 너무 자세하게 표현하지 않고 더 명확하게 표현할 수있는 추가 단어 제안을 환영합니다.
mtraceur

2
내가 유닉스와 관련하여 젊은 엔지니어로 들었던 첫 번째 것은 "Everything Is A File"이었고 나는 여러분이 수도를들을 수 있다고 맹세합니다. 그리고 그 아이디어를 조기에 받아들이면 유닉스 / 리눅스가 이해하기 훨씬 쉬워 보입니다. 리눅스는 그 디자인 철학의 대부분을 물려 받았습니다. 누군가 언급 한 것이 기쁘다.
StephenG

2
@PeterCordes, DOS NUL는 모든 파일 이름에 매직 파일 이름이 나타나 도록하여 입력 문제를 "해결했습니다" > NUL.
Cristian Ciupitu

15

내가 생각하는 /dev/nullA는 문자 장치 (즉, 일반 파일처럼 동작) 대신에 대한 programm에 성능 이유는 .

프로그램 인 경우 프로그램을로드, 시작, 스케줄링, 실행 한 후 프로그램을 중지 및 언로드해야합니다. 설명하는 간단한 C 프로그램은 많은 리소스를 소비하지는 않지만 프로세스 관리 작업이 대규모로 비용이 많이 들기 때문에 많은 수의 (예 : 수백만) 리디렉션 / 배관 작업을 고려할 때 큰 차이가 있다고 생각합니다. 여기에는 컨텍스트 전환이 포함됩니다.

또 다른 가정 : 프로그램에 파이핑하려면 수신 프로그램 이 메모리를 할당 해야합니다 ( 메모리 는 나중에 직접 폐기하더라도). 따라서 공구에 파이프를 연결하면 송신 프로그램과 수신 프로그램에서 두 번의 메모리 소비가 발생합니다.


10
설치 비용뿐만 아니라 파이프에 쓸 때마다 메모리 복사가 필요하고 읽기 프로그램으로 전환하는 컨텍스트가 필요합니다. (또는 파이프 버퍼가 가득 찼을 때 컨텍스트 전환이 필요합니다. 그리고 독자는 read데이터가 있을 때 다른 사본을 작성해야 합니다). 유닉스가 설계된 단일 코어 PDP-11에서는 무시할 수 없습니다! 메모리 대역폭 / 복사는 오늘날보다 훨씬 저렴합니다. writeFD 열기에 대한 시스템 호출 /dev/null은 버퍼에서 데이터를 읽지 않아도 즉시 반환 될 수 있습니다.
피터 코 데스

@ PeterCordes, 내 노트는 접선이지만 역설적으로 오늘날의 메모리 쓰기가 그 어느 때보 다 비쌀 수 있습니다. 8 코어 CPU는 클럭 시간에 16 개의 정수 연산을 수행하는 반면 엔드 투 엔드 메모리 쓰기는 16 클럭 (4GHz CPU, 250MHz RAM)으로 완료됩니다. 256의 요소입니다. 최신 CPU의 RAM은 PRL-11 CPU의 RL02와 비슷하며 주변 장치 저장 장치와 거의 같습니다! :) 간단하고 자연 스럽지는 않지만 캐시에 충돌하는 모든 내용이 기록되며 쓸모없는 쓰기는 항상 중요한 캐시 공간에 대한 다른 계산을 박탈합니다.
kkm

@kkm : 예, 커널의 파이프 버퍼에 약 2x 128kiB의 L3 캐시 풋 프린트를 낭비하고 null프로그램 의 읽기 버퍼가 빨라지 지만 대부분의 멀티 코어 CPU는 항상 모든 코어를 사용하지 않고 실행되지 않습니다. null프로그램 을 실행하는 CPU 시간 은 대부분 비어 있습니다. 모든 코어가 막힌 시스템에서는 쓸모없는 배관이 더 큰 문제입니다. 그러나 "핫"버퍼는 RAM으로 플러시되지 않고 여러 번 다시 작성할 수 있으므로 캐시가 아닌 L3 대역폭에 대해서만 경쟁하고 있습니다. 특히 동일한 물리적 시스템의 다른 논리 코어가 경쟁하는 SMT (하이퍼 스레딩) 시스템에서는 좋지 않습니다.
Peter Cordes

.... 그러나 메모리 계산되어 매우 결함. 최신 CPU는 메모리 병렬 처리가 많기 때문에 DRAM 대기 시간 이 200-400 코어 클럭주기 및 L3> 40과 같지만 대역폭 은 ~ 8 ​​바이트 / 클럭입니다. (놀랍게도 L3 또는 DRAM 에 대한 단일 스레드 대역폭은 쿼드 코어 메모리 대 쿼드 코어 데스크톱이있는 많은 코어 Xeon에서 한 코어가 비행 중에 유지할 수있는 요청의 최대 동시성에 의해 제한되기 때문에 더 나쁩니다 . max_concurrency / 대기 시간 : 단일 스레드 메모리 처리량에서 Skylake가 Broadwell-E보다 훨씬 우수한 이유는 무엇입니까? )
Peter Cordes

... 쿼드 코어와 18 코어를 비교 한 Haswell 숫자 는 7-cpu.com/cpu/Haswell.html 도 참조하십시오 . 어쨌든, 현대 CPU는 메모리를 기다리지 않으면 시계 당 엄청난 양의 작업을 수행 할 수 있습니다. 1993 년의 펜티엄이나 현대적인 저가형 듀얼 이슈 ARM과 같이 시계 당 2 개의 ALU 연산 만있는 것으로 보입니다. Ryzen 또는 스웰은 잠재적으로 4 스칼라 정수 ALU 본부 + 2 개 메모리 작전 수행 코어 당 클럭 당, 또는 훨씬 더 SIMD로한다. 예를 들어 Skylake-AVX512는 vpaddd zmm명령 당 16 개의 32 비트 요소 에서 (코어 당) 클럭 당 2 개의 처리량을 갖습니다 .
피터 코 데스

7

"모든 것이 파일"인 것 외에도 대부분의 다른 답변이 기반으로하는 모든 곳에서 사용의 용이성 외에도 @ user5626466이 언급 한 것처럼 성능 문제가 있습니다.

실제로 보여주기 위해 다음과 같은 간단한 프로그램을 만듭니다 nullread.c.

#include <unistd.h>
char buf[1024*1024];
int main() {
        while (read(0, buf, sizeof(buf)) > 0);
}

와 그것을 컴파일 gcc -O2 -Wall -W nullread.c -o nullread

(참고 : 파이프에서는 lseek (2)를 사용할 수 없으므로 파이프를 비우는 방법은 파이프가 비워 질 때까지 파이프를 읽는 것입니다.)

% time dd if=/dev/zero bs=1M count=5000 |  ./nullread
5242880000 bytes (5,2 GB, 4,9 GiB) copied, 9,33127 s, 562 MB/s
dd if=/dev/zero bs=1M count=5000  0,06s user 5,66s system 61% cpu 9,340 total
./nullread  0,02s user 3,90s system 41% cpu 9,337 total

반면 표준 /dev/null파일 리디렉션을 사용하면 컨텍스트 전환이 적고 커널이 데이터를 복사하는 대신 데이터를 무시하는 등의 사실로 인해 속도가 훨씬 빨라집니다.

% time dd if=/dev/zero bs=1M count=5000 > /dev/null
5242880000 bytes (5,2 GB, 4,9 GiB) copied, 1,08947 s, 4,8 GB/s
dd if=/dev/zero bs=1M count=5000 > /dev/null  0,01s user 1,08s system 99% cpu 1,094 total

(이것은 의견이 있어야하지만 너무 커서 너무 읽을 수 없습니다)


어떤 하드웨어를 테스트 했습니까? 4.8GB / s는 Skylake i7-6700k (DDR4-2666)에서 얻을 수있는 23GB / s에 비해 상당히 낮지 만 L3 캐시에서는 버퍼가 뜨겁게 유지되므로 스펙터를 사용하면 시스템 호출 비용이 비쌉니다. + 멜트 다운 완화 지원 파이프 버퍼가 1M보다 작기 때문에 배관에 이중 문제가 발생하여 쓰기 / 읽기 시스템 호출이 더 많지만 예상보다 10 배에 가까운 성능 차이가 나쁘지만 스카이 레이크 시스템의 경우 23GB / s와 비교합니다. x86-64 Linux 4.15.8-1-ARCH를 실행하는 3.3GB / s 이므로 6.8 배입니다. 이제 시스템 호출 비용많이 듭니다 )
Peter Cordes

1
64K 파이프 버퍼를 갖춘 @PeterCordes 3GB / s는 초당 2x 103124 syscalls를 제안합니다. 초당 200000 개의 syscall이있는 서버 CPU에서는 작업 세트가 거의 없기 때문에 PTI에서 ~ 8 %의 오버 헤드를 예상 할 수 있습니다. (내가 참조하는 그래프에는 PCID 최적화가 포함되어 있지 않지만 소규모 작업 세트에는 그다지 중요하지 않습니다). PTI에 큰 영향이 있는지 잘 모르겠습니다. brendangregg.com/blog/2018-02-09/…
sourcejedi

1
흥미 롭습니다. 2MB의 L2 캐시를 가진 Silvermont 이므로 dd버퍼 + 수신 버퍼가 맞지 않습니다. 아마도 마지막 레벨 캐시 대역폭 대신 메모리 대역폭을 다루고있을 것입니다. 512k 버퍼 또는 64k 버퍼로 더 나은 대역폭을 얻을 수 있습니다. (에 따르면 strace내 바탕 화면에, write그리고 read1048576을 반환하는, 그래서 그 우리는 사용자가 지불하는 의미한다고 생각 <->., 64K 당하지, 한 번 MiB 크기 당 TLB 무효화 + 브랜치 예측의 커널 비용 플러시 @sourcejedi을 그것은 유령이다 비용이 가장 많이 드는 완화책이라고 생각합니다)
Peter Cordes

1
@sourcejedi : 유령 완화이 활성화하는 비용 syscall바로와 반환 ENOSYS유령 완화와 스카이 레이크에 ~ 1800 사이클은 대부분되는 활성화 wrmsrBPU를 무효화하는, BeeOnRope의 테스트 @를 따라 . 완화가 비활성화 된 경우 사용자-> 커널-> 사용자 왕복 시간은 ~ 160 사이클입니다. 당신은하지만 있는 메모리의 감동을 많이, 붕괴 완화도 중요하다. Hugepages가 도움이 될 것입니다 (더 적은 TLB 항목을 다시로드해야 함).
Peter Cordes

1
@PeterCordes 단일 코어 유닉스 시스템에서는 64K 당 1 개의 컨텍스트 스위치 또는 파이프 버퍼가 무엇이든간에 분명히 상처를 입을 것입니다 ... 실제로 [2 개의 CPU 코어를 가진 동일한 수의 컨텍스트 스위치] ( unix.stackexchange.com/questions/439260/… ); 또한 각 64k에 대한 절전 / 깨우기주기를 컨텍스트 스위치 (공칭 "유휴 프로세스"로)로 계산해야합니다. 동일한 CPU에서 파이프 라인 프로세스를 유지하면 실제로 두 배 이상 빠르게 작동했습니다.
sourcejedi

6

귀하의 질문은 파일 대신 null 프로그램을 사용하여 간단하게 얻을 수있는 것처럼 보입니다. 아마도 우리는 "매직 파일"이라는 개념을 제거하고 대신 "일반 파이프"를 가질 수 있습니다.

그러나 파이프도 파일이라는 것을 고려 하십시오 . 일반적으로 이름이 지정되지 않았으므로 파일 디스크립터를 통해서만 조작 할 수 있습니다.

이 다소 고안된 예를 고려하십시오.

$ echo -e 'foo\nbar\nbaz' | grep foo
foo

Bash의 프로세스 대체를 사용하면 더 둥근 길을 통해 동일한 것을 달성 할 수 있습니다.

$ grep foo <(echo -e 'foo\nbar\nbaz')
foo

을 바꾸기 grep위해 echo우리는 내부적으로 볼 수 있습니다 :

$ echo foo <(echo -e 'foo\nbar\nbaz')
foo /dev/fd/63

<(...)구조는 단지 파일 이름으로 대체하고, GREP은 오래된 파일을 여는, 그냥 익명을 어떻게 생각됩니다 /dev/fd/63. 여기, /dev/fd파일이 액세스하는 모든 파일 설명자에 대해 명명 된 파이프를 만드는 매직 디렉토리입니다.

일반 파일과 같이 모든 것이 mkfifo표시되는 명명 된 파이프를 만드는 것이 마술을 덜 만들 수 ls있습니다.

$ mkfifo foofifo
$ ls -l foofifo 
prw-rw-r-- 1 indigo indigo 0 Apr 19 22:01 foofifo
$ grep foo foofifo

다른 곳 :

$ echo -e 'foo\nbar\nbaz' > foofifo

보라, grep이 출력 할 것이다 foo.

파이프와 일반 파일을 인식하고 / dev / null과 같은 특수 파일이 모두 파일 일 뿐이라고 생각하면 null 프로그램을 구현하는 것이 복잡합니다. 커널은 파일에 대한 쓰기를 어느 쪽이든 처리해야하지만 / dev / null의 경우 쓰기를 바닥에 떨어 뜨릴 수 있지만 파이프를 사용하면 실제로 바이트를 다른 프로그램으로 전송해야합니다. 실제로 읽어보십시오.


@Lyle 그래? 그렇다면 왜 에코가 인쇄 /dev/fd/63됩니까?
Phil Frost

흠. 좋은 지적. 글쎄, 이것은 쉘로 구현되었으므로 아마도 당신의 쉘은 내가 자란 이전 Bourne 쉘과 다를 수 있습니다.
Lyle

한 가지 차이점은 echo는 stdin에서 읽지 않지만 grep은 읽지 만 쉘이 실행하기 전에 어떻게 알 수 있는지 생각할 수 없습니다.
Lyle

1
그리고 strace는 이것을 명확하게 만듭니다. bash를 사용하면 정확히 맞습니다. '<(...)'구문은 <filename과는 상당히 다른 일을하고 있습니다. 흠. 나는 무언가를 배웠다.
Lyle

0

역사적인 패러다임과 성능을 넘어서는 보안 문제가 있다고 주장합니다. 권한이있는 실행 자격 증명이있는 프로그램 수를 제한하는 것은 아무리 간단하더라도 시스템 보안의 기본 원칙입니다. /dev/null시스템 서비스에서 사용하기 때문에 그러한 특권을 가지려면 반드시 교체 해야합니다. 최신 보안 프레임 워크는 악용을 방지하는 훌륭한 작업을 수행하지만 절대 안전하지는 않습니다. 파일로 액세스 한 커널 구동 장치는 훨씬 더 악용하기가 어렵습니다.


말도 안되는 소리. 버그가없는 커널 드라이버를 작성하는 것은 stdin을 읽고 버리는 버그가없는 프로그램을 작성하는 것보다 쉽지 않습니다. 그것은 모두 그래서,이 setuid 또는 아무것도 할 필요가 없습니다 /dev/null또는 제안 된 입력 폐기 프로그램, 공격 벡터가 같은 것 : 이상한 뭔가를 루트로 실행되는 스크립트 또는 프로그램을 얻을 (같은 시도 lseek/dev/null또는 오픈 동일한 프로세스에서 여러 번 또는 IDK 또는 /bin/null이상한 환경으로 호출하십시오 .
Peter Cordes

0

다른 사람이 이미 지적했듯이, /dev/null 코드 라인의 소수 만든 프로그램. 이 코드 줄은 커널의 일부입니다.

보다 명확하게하기 위해 Linux 구현은 다음과 같습니다. 문자 장치는 읽거나 쓸 때 함수를 호출합니다. 에 쓰기 /dev/null통화 write_null 읽기 호출 동안, read_null 등록 여기 .

말 그대로 몇 줄의 코드 :이 함수는 아무것도하지 않습니다. 읽고 쓰는 것 이외의 기능을 세는 경우에만 손의 손가락보다 더 많은 코드 줄이 필요합니다.


어쩌면 내가 더 정확하게 말했을 것입니다. 프로그램 대신 char 장치로 구현하는 이유를 의미했습니다. 어느 쪽이든 몇 줄이지 만 프로그램 구현은 훨씬 간단합니다. 다른 답변이 지적했듯이 이것에는 꽤 많은 이점이 있습니다. 그들 중 효율성과 휴대 성 최고.
Ankur S

확실한. 실제 구현이 재미 있었기 때문에이 답변을 추가했습니다 (최근에 스스로 발견했습니다). 그러나 진짜 이유는 다른 사람들이 실제로 지적한 것입니다.
Matthieu Moy

나도! 나는 최근에 리눅스에서 장치를 배우기 시작했고 대답은 상당히 유익했다
Ankur S

-2

/ dev / chargen / dev / zero와 / dev / null을 포함한 다른 사람들도 알고 있기를 바랍니다.

LINUX / UNIX는이 중 몇 가지를 제공하므로 사람들이 WELL WRITTEN CODE FRAGMEnTS를 잘 활용할 수 있습니다.

Chargen은 특정하고 반복되는 문자 패턴을 생성하도록 설계되었습니다. 속도가 매우 빠르며 직렬 장치의 한계를 뛰어 넘고 테스트 또는 기타 테스트에 실패하거나 실패한 직렬 프로토콜을 디버깅하는 데 도움이됩니다.

Zero는 기존 파일을 채우거나 많은 0을 출력하도록 설계되었습니다.

/ dev / null은 같은 생각을 가진 또 다른 도구 일뿐입니다.

툴킷에있는 이러한 모든 도구는 기존 프로그램이 장치 또는 파일 교체와 같은 특정 요구 사항에 관계없이 고유 한 작업을 수행 할 수있는 기회가 절반임을 의미합니다.

LINUX 버전의 문자 장치 몇 개만 제공하면 누가 가장 흥미로운 결과를 낼 수 있는지 공모를 설정할 수 있습니다.

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