태그 보관물: proc

proc

내장 된 일부 ‘read’내장 쉘이`/ proc`의 파일에서 전체 줄을 읽지 못하는 이유는 무엇입니까? 라인을 읽을 수없는 내장 /proc(아래에서

일부 본쉘의 read에서 파일의 전체 라인을 읽을 수없는 내장 /proc(아래에서 실행해야 할 명령 zsh, 대체 $=shell$shell다른 껍질을) :

$ for shell in bash dash ksh mksh yash zsh schily-sh heirloom-sh "busybox sh"; do
  printf '[%s]\n' "$shell"
  $=shell -c 'IFS= read x </proc/sys/fs/file-max; echo "$x"'
done
[bash]
602160
[dash]
6
[ksh]
602160
[mksh]
6
[yash]
6
[zsh]
6
[schily-sh]
602160
[heirloom-sh]
602160
[busybox sh]
6

read표준은 표준 입력이 텍스트 파일이어야 한다고 요구하는데, 그 요구로 인해 다양한 동작이 발생합니까?


텍스트 파일 의 POSIX 정의를 읽고 확인을하십시오.

$ od -t a </proc/sys/fs/file-max
0000000   6   0   2   1   6   0  nl
0000007

$ find /proc/sys/fs -type f -name 'file-max'
/proc/sys/fs/file-max

아무 없다 NUL의 내용의 문자 /proc/sys/fs/file-max, 또한 find일반 파일로보고 (이 버그인가 find?).

나는 껍질이 후드 아래에서 뭔가를 한 것 같아요 file.

$ file /proc/sys/fs/file-max
/proc/sys/fs/file-max: empty



답변

문제는 /procLinux의 해당 파일이 텍스트 파일로 표시되는 것처럼 stat()/fstat()보이지만 그렇게 동작하지 않는다는 것입니다.

동적 데이터이기 때문에 하나 이상의 read()시스템 호출 만 수행 할 수 있습니다 (적어도 일부는 해당). 하나 이상의 작업을 수행하면 두 개의 다른 내용으로 된 두 개의 청크를 얻을 수 있으므로 대신 두 번째 청크 read()는 아무것도 반환하지 않습니다 (파일 끝을 의미) ( lseek()처음으로 돌아 가지 않고 시작 부분으로 돌아 가지 않는 한 ).

read유틸리티는 개행 문자 뒤로 읽어 확실하지 않은 것으로 한 바이트 한 번에 파일의 내용을 읽을 필요가있다. 즉 무엇 dash을 수행합니다

 $ strace -fe read dash -c 'read a < /proc/sys/fs/file-max'
 read(0, "1", 1)                         = 1
 read(0, "", 1)                          = 0

일부 쉘은 시스템 호출을 bash너무 많이하지 않아도되도록 최적화되어 read()있습니다. 그들은 먼저 파일을 찾을 수 있는지 확인하고, 그렇다면 파일을 읽은 후 줄 바꿈 바로 다음에 커서를 다시 넣을 수 있다는 것을 알고 덩어리로 읽습니다.

$ strace -e lseek,read bash -c 'read a' < /proc/sys/fs/file-max
lseek(0, 0, SEEK_CUR)                   = 0
read(0, "1628689\n", 128)               = 8

를 사용하면 bash128 바이트보다 큰 proc 파일에는 여전히 문제가 있으며 한 번의 읽기 시스템 호출에서만 읽을 수 있습니다.

bash-d옵션을 사용할 때 해당 최적화를 비활성화하는 것으로 보입니다 .

ksh93가짜가 될 정도로 최적화를 더욱 강화합니다. ksh93의의는 read다시 찾아 않지만, 다음에 대한 읽기 추가 데이터를 기억 read다음, 그래서 read(또는 같은 데이터를 읽을의 다른 내장 매크로의 cat또는 head)도 시도하지 않는다 read(즉, 데이터가 수정 된 경우에도 데이터 사이에 다른 명령) :

$ seq 10 > a; ksh -c 'read a; echo test > a; read b; echo "$a $b"' < a
1 2
$ seq 10 > a; sh -c 'read a; echo test > a; read b; echo "$a $b"' < a
1 st


답변

왜 그런지 알고 싶다면 ? 이것은 커널 소스 에서 답을 볼 수 있습니다 :

    if (!data || !table->maxlen || !*lenp || (*ppos && !write)) {
            *lenp = 0;
            return 0;
    }

기본적으로 탐색 ( *ppos0 아님)은 !write숫자 인 sysctl 값의 읽기 ( )에 대해 구현되지 않습니다 . 에서 읽기를 수행 할 때마다 동일한 파일 의 구성 테이블 항목에서 해당 /proc/sys/fs/file-max루틴
__do_proc_doulongvec_minmax()이 호출 됩니다.file-max

검색을 허용하는 /proc/sys/kernel/poweroff_cmdvia
와 같은 다른 항목을 proc_dostring()사용하면 dd bs=1문제없이 쉘에서 읽을 수 있습니다.

커널 2.6 이후 대부분의 /proc읽기는 seq_file 이라는 새로운 API를 통해 구현되었으며 검색을

지원하므로 읽기 /proc/stat가 문제를 일으키지 않아야합니다. /proc/sys/구현은, 우리가 볼 수 있듯이,이 API를 사용하지 않습니다.


답변

첫 번째 시도에서 이것은 실제 Bourne Shell 또는 그 파생 상품 (sh, bosh, ksh, heirloom)보다 적은 값을 반환하는 쉘의 버그처럼 보입니다.

원래 Bourne Shell은 블록 (64 바이트)을 읽으려고합니다. 최신 Bourne Shell 변형은 128 바이트를 읽지 만 줄 바꿈 문자가 없으면 다시 읽기 시작합니다.

배경 : / procfs 및 이와 유사한 구현 (예 : 탑재 된 /etc/mtab가상 파일)에는 동적 내용이 있으며 stat()호출로 인해 동적 내용이 먼저 재생성 되지 않습니다 . 따라서 이러한 파일의 크기 (읽기에서 EOF까지)는 stat()반환 되는 크기와 다를 수 있습니다 .

POSIX 표준에 따라 유틸리티 는 언제든지 짧은 읽기 를 기대해야하므로 read(), 주문 된 바이트 수 보다 적은 값을 리턴 하는 것이 EOF 표시 라고 생각하는 소프트웨어 가 손상되었습니다. 올바르게 구현 된 유틸리티 read()는 0이 반환 될 때까지 예상보다 적게 반환되는 경우 다시 호출 합니다. read내장의 경우 물론 a 가 보일 때 까지 EOF 또는 읽을 때까지 읽는 것이 충분합니다 NL.

실행 truss하거나 트러스 복제 를 수행 하는 경우 6실험 에서만 반환 되는 셸에 대한 잘못된 동작을 확인할 수 있습니다 .

이 특별한 경우에는 Linux 커널 버그 인 것 같습니다.

$ sdd -debug bs=1 if= /proc/sys/fs/file-max
Simple copy ...
readbuf  (3, 12AC000, 1) = 1
writebuf (1, 12AC000, 1)
8readbuf  (3, 12AC000, 1) = 0

sdd: Read  1 records + 0 bytes (total of 1 bytes = 0.00k).
sdd: Wrote 1 records + 0 bytes (total of 1 bytes = 0.00k).

리눅스 커널은 두 번째 로 0 을 반환 read하고 이것은 물론 올바르지 않습니다.

결론 : 충분한 양의 데이터를 먼저 읽으려고 시도하는 쉘은이 Linux 커널 버그를 유발하지 않습니다.


답변

/ proc 아래의 파일은 때로는 NULL 문자를 사용하여 파일 내부의 필드를 구분합니다. 읽기가 이것을 처리 할 수없는 것 같습니다.


답변