구문 분석 /proc/net/tcp/
하고 싶지만 안전합니까?
/proc/
다른 프로세스 (또는 OS 자체)가 동시에 파일을 변경한다는 것을 두려워하지 말고 파일을 열고 읽으려면 어떻게해야 합니까?
sysctl
구문 분석에 어떻게 도움 이 /proc/net/tcp/
됩니까?
구문 분석 /proc/net/tcp/
하고 싶지만 안전합니까?
/proc/
다른 프로세스 (또는 OS 자체)가 동시에 파일을 변경한다는 것을 두려워하지 말고 파일을 열고 읽으려면 어떻게해야 합니까?
sysctl
구문 분석에 어떻게 도움 이 /proc/net/tcp/
됩니까?
답변:
일반적으로 아닙니다. (따라서 대부분의 답변이 잘못되었습니다.) 원하는 속성에 따라 안전 할 수 있습니다. 그러나의 파일 일관성에 대해 너무 많이 가정하면 코드의 버그로 끝나기 쉽습니다 /proc
. 예를 들어, 일관된 스냅 샷 이라고 가정 한이 버그를/proc/mounts
참조하십시오 .
예를 들면 다음과 같습니다.
/proc/uptime
이다 완전히 원자 누군가가 다른 답변에서 언급 한 바와 같이, - 그러나 단지 리눅스 2.6.30 이후 채 2 세입니다. 따라서이 작고 사소한 파일조차도 그때까지 경쟁 조건에 처해 있었고 여전히 대부분의 엔터프라이즈 커널에 있습니다. fs/proc/uptime.c
현재 소스 또는 원자로 만든 커밋을 참조하십시오 . 2.6.30 이전의 커널에서는 약간의 open
파일을 만들 수 read
있습니다. 나중에 다시 돌아 오면 read
얻는 부분이 첫 번째 부분과 일치하지 않습니다. (방금 이것을 시연했습니다-재미를 위해 직접 시도하십시오.)
/proc/mounts
인 단일 원자 내의 read
시스템 콜. 따라서 read
전체 파일을 한 번에 모두 확보하면 시스템에서 마운트 지점의 일관된 단일 스냅 샷이 생성됩니다. 그러나 여러 read
시스템 호출 을 사용하는 경우 (파일이 크면 정상적인 I / O 라이브러리를 사용하고이 문제에 특별한주의를 기울이지 않으면 정확하게 발생합니다.) 질환. 일관된 스냅 샷을 얻을 수있을뿐만 아니라 시작하기 전에 존재했거나 존재를 멈추지 않은 마운트 지점이 보이지 않을 수 있습니다. 그것은 하나의 원자의 것을보고 read()
보기에서 m_start()
의fs/namespace.c
그것은 세마포어를 잡아 볼 것을 경비원이 될 때까지 계속 마운트 포인트의 목록, m_stop()
호출, 때read()
수행. 무엇이 잘못 될 수 있는지 확인하려면 작년의이 버그 (위에 링크 한 것과 동일한 버그)를 참고하십시오 /proc/mounts
.
/proc/net/tcp
실제로 묻는 것보다 그 일관성이 떨어집니다. 그건 단지 테이블의 각 행 내에서 원자 . 에서이, 모양을 보려면 listening_get_next()
에서net/ipv4/tcp_ipv4.c
와 established_get_next()
똑같이 파일에 아래와 자물쇠를 볼 그들은 차례로 각 항목에 꺼내. 행마다 일관성이 부족하다는 것을 보여주기 위해 편리한 재현 코드가 없지만 일관성을 유지하는 잠금 장치 (또는 다른 것)는 없습니다. 네트워크는 종종 시스템의 매우 바쁜 부분이므로이 진단 도구에서 일관된 견해를 제시하는 것은 가치가 없습니다.
계속 다른 부분 /proc/net/tcp
의 각 행 내에서 원자는에서 버퍼링 seq_read()
당신이 읽을 수 있는fs/seq_file.c
. 이렇게하면 read()
한 행의 일부 가되면 전체 행의 텍스트가 버퍼에 유지되므로 다음 read()
행이 새 행을 시작하기 전에 나머지 행을 가져옵니다. /proc/mounts
여러 read()
호출 을 수행하더라도 동일한 메커니즘이 각 행을 원자로 유지 하는 데 사용 /proc/uptime
되며 최신 커널에서는 원자를 유지하는 데 사용 되는 메커니즘이기도합니다 . 커널은 메모리 사용에 대해 신중하기 때문에이 메커니즘은 전체 파일을 버퍼링 하지 않습니다 .
에있는 대부분의 파일은 /proc
적어도 일관되게 유지되며 /proc/net/tcp
, 각 행은 제공하는 정보에 관계없이 하나의 항목을 일관된 그림으로 표시합니다. 대부분의 파일 은 동일한 seq_file
추상화를 사용하기 때문 입니다. 그러나이 /proc/uptime
예에서 알 수 있듯이 일부 파일은 seq_file
2009 년 에 사용하기 위해 여전히 마이그레이션되고 있습니다 . 나는 여전히 오래된 메커니즘을 사용하고 그 정도의 원 자성을 갖지 않는 것도 있습니다. 이 경고는 거의 문서화되어 있지 않습니다. 주어진 파일에 대한 유일한 보증은 소스를 읽는 것입니다.
의 경우 /proc/net/tcp
,이를 읽고 두려움없이 각 행을 구문 분석 할 수 있습니다. 그러나 한 번에 여러 줄에서 결론을 얻으려고하면 다른 프로세스와 커널 이 읽는 동안 변경하고 버그를 생성 할 수 있습니다.
clock_gettime(2)
입니다 CLOCK_MONOTONIC
(아마도 내가 알지 못하는 기술이 있지만 개인적으로 부팅 시간 이후에만 보았습니다). Linux의 경우 옵션도 있습니다 sysinfo(2)
.
의 파일이 있지만 /proc
사용자 공간에서 일반 파일로 표시, 그들이 진짜로 사용자 공간에서 표준 파일 작업을 지원 파일이 아니라 실체없는 ( open
, read
, close
). 이것은 커널에 의해 변경되는 디스크에 일반 파일이있는 것과는 상당히 다릅니다.
모든 커널은 sprintf
-like 함수를 사용하여 내부 상태를 자체 메모리로 인쇄하고 read(2)
시스템 호출 을 실행할 때마다 해당 메모리가 사용자 공간에 복사됩니다 .
커널은 이러한 호출을 일반 파일과는 완전히 다른 방식으로 처리하므로 읽을 때 데이터의 전체 스냅 샷을 준비 할 수 있고 open(2)
동시에 커널은 동시 호출이 일관되고 원자적임을 보장 할 수 있습니다. 나는 그것을 아무데도 읽지 못했지만, 그렇지 않으면 실제로 의미가 없습니다.
내 조언은 특정 Unix 풍미에서 proc 파일의 구현을 살펴 보는 것입니다. 이것은 실제로 표준에 의해 통제되지 않는 구현 문제입니다 (출력 형식 및 내용 그대로).
가장 간단한 예는 uptime
Linux 에서 proc 파일을 구현하는 것입니다 . 에 제공된 콜백 함수에서 전체 버퍼가 어떻게 생성되는지 확인하십시오 single_open
.
proc
파일이 커널에 의해 쓰기 위해 열린 일반 파일 이라고 생각하는 인상을 남겼 기 때문에 OP를이 방향으로 가리키고 있습니다.
open()
파일이 모두 스냅 샷되었다는 추측 은 많은 파일, 특히 /proc/net/tcp
OP와 관련하여 잘못되었습니다 . 이러한 의미를 제공하는 비용에 대해 생각한다면 이는 의미가 있습니다. 모든 TCP 연결을 기록하는 내부 데이터 구조를 잠그는 것과 같은 작업을 수행해야합니다. 데이터를 스캔하고 버퍼로 포맷하기에 충분합니다. 실제로 일어나는 일에 대한 자세한 내용은 내 대답을 참조하십시오.
/ proc은 가상 파일 시스템입니다. 실제로 커널 내부를 편리하게 볼 수 있습니다. 읽는 것이 안전하지만 (여기있는 이유) 가상 파일의 내부가 최신 버전의 커널로 발전 할 수 있기 때문에 장기적으로 위험합니다.
편집하다
Linux 커널 문서 , 1.4 장 네트워킹의 proc 문서에서 더 많은 정보를 얻을 수 있습니다. 시간이지나면서 정보가 어떻게 진화하는지 정보를 찾을 수 없습니다. 나는 그것이 얼어 붙었다 고 생각했지만 명확한 대답을 할 수는 없습니다.
편집 2
Sco doc 에 따르면 (리눅스는 아니지만 * nix의 모든 맛이 그렇게 작동한다고 확신합니다)
프로세스 상태 및 결과적으로 / proc 파일의 내용이 인스턴트에서 인스턴트로 변경 될 수 있지만 / proc 파일의 단일 read (2)는 상태의``정상적인 ''표현을 반환합니다. 즉, 읽기는 프로세스 상태의 원 자성 스냅 샷 실행중인 프로세스의 / proc 파일에 적용된 연속 읽기에는 이러한 보장이 적용되지 않습니다. 또한 as (주소 공간) 파일에 적용된 I / O에 대해서는 원 자성이 보장되지 않습니다. 프로세스 주소 공간의 내용은 해당 프로세스의 LWP 또는 시스템의 다른 프로세스에 의해 동시에 수정 될 수 있습니다.
proc
다른 커널간에 비슷한 행동 을하는 것처럼 (또는 존재한다고 가정 할 때) 유닉스 시스템에서는 필요하지 않다고 생각합니다. )가 당신에게 상처를 줄 것입니다.
/proc/net/tcp
OP의 주요 관심사 인 사실이 아닙니다 . 오히려 출력의 각 개별 행만 원자 적입니다. 자세한 내용은 내 답변을 참조하십시오.
Linux 커널의 procfs API는 읽기가 일관된 데이터를 리턴하도록 인터페이스를 제공합니다. 의 의견을 읽으십시오 __proc_file_read
. 큰 주석 블록의 항목 1)이이 인터페이스를 설명합니다.
즉, 반환 된 데이터의 일관성을 유지하기 위해이 인터페이스를 올바르게 사용하는 것은 특정 proc 파일의 구현에 달려 있습니다. 따라서 귀하의 질문에 대답하기 위해 : 아니오, 커널은 읽는 동안 proc 파일의 일관성을 보장하지 않지만 일관성을 제공하기 위해 해당 파일의 구현 수단을 제공합니다.
/proc
은 실제로 일관성을 제공하지 않습니다. 자세한 내용은 내 답변을 참조하십시오.
__proc_file_read()
에 찬성하여 더 이상 사용되지 않습니다 seq_file
. 긴 블록 주석 바로 위의 다소 분노한 주석 (Linus의 주석)을 참조하십시오.
임베디드 ARM 대상에서 현재 드라이버 개발을 수행하고 있기 때문에 Linux 2.6.27.8에 대한 소스가 있습니다.
linux-2.6.27.8-lpc32xx/net/ipv4/raw.c
934 행 의 파일은 다음과 같습니다.
seq_printf(seq, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n",
i, src, srcp, dest, destp, sp->sk_state,
atomic_read(&sp->sk_wmem_alloc),
atomic_read(&sp->sk_rmem_alloc),
0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp),
atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
어떤 출력
[wally@zenetfedora ~]$ cat /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 017AA8C0:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 15160 1 f552de00 299
1: 00000000:C775 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 13237 1 f552ca00 299
...
함수 raw_sock_seq_show()
의 계층 구조의 일부인 procfs의 처리 함수. procfs 읽기가 정보를 업데이트하는 것보다 훨씬 덜 일반적 이기 때문에 텍스트는 파일을 read()
요청할 때까지 텍스트가 생성되지 않습니다 ./proc/net/tcp
내와 같은 일부 드라이버는 single로 proc_read 함수를 구현합니다 sprintf()
. 핵심 드라이버 구현의 추가 문제는 단일 읽기 동안 중간 커널 공간 버퍼에 맞지 않을 수있는 매우 긴 출력을 처리하는 것입니다.
64K 읽기 버퍼를 사용하는 프로그램으로 테스트했지만 proc_read가 데이터를 반환하기 위해 시스템에서 3072 바이트의 커널 공간 버퍼가 발생합니다. 많은 양의 텍스트를 반환하려면 고급 포인터로 여러 번의 호출이 필요합니다. 둘 이상의 I / O가 필요할 때 반환 된 데이터를 일관되게 만드는 올바른 방법을 모르겠습니다. 확실히 각 항목 /proc/net/tcp
은 일관성이 있습니다. 나란히 라인이 다른 시간에 스냅 샷 될 가능성이 있습니다.
ifstream
안전하지 않지만 사용 read
하면 안전하다는 것을 의미합니까? 또는 ifstream
내부적으로 사용 read
합니까? 그리고 당신은 무엇을 제안합니까?
/proc/net/tcp
형식이 어떻게 지정 되는지에 대한 설명이며 다른 사람이 데이터를 읽는 방법과는 완전히 독립적입니다.
/proc/net/tcp
)이 동일한 스냅 샷에서 나온 것이 아니라고 추측합니다 . 몇 가지 설명은 내 답변을 참조하십시오.
알려지지 않은 버그가 없으면 /proc
손상된 데이터를 읽거나 오래된 데이터와 새 데이터를 혼합하여 사용할 수 있는 경쟁 조건이 없습니다 . 이런 의미에서 안전합니다. 그러나 여전히 읽은 많은 데이터 /proc
가 생성 되 자마자 시간이 지남에 따라 경쟁 조건이 남아 있으며 , 더 나아가서 읽고 / 처리 할 때까지 더 오래 걸릴 수 있습니다. 예를 들어 프로세스는 언제든지 죽을 수 있으며 새로운 프로세스에 동일한 pid를 할당 할 수 있습니다. 경쟁 조건없이 사용할 수있는 유일한 프로세스 ID는 자신의 자식 프로세스입니다. 네트워크 정보 (오픈 포트 등)와 대부분의 정보도 마찬가지입니다 /proc
. 나는 데이터에 의존하는 것이 나쁘고 위험한 관행이라고 생각합니다./proc
자신의 프로세스 및 잠재적으로 자식 프로세스에 대한 데이터를 제외하고는 정확합니다. 물론 /proc
정보 / 로깅 등을 위해 사용자 / 관리자에게 다른 정보를 제공하는 것이 여전히 유용 할 수 있습니다 . 목적.
getpid()
/proc
인터페이스에 관한 한, 그들은 모두 같은 약점과 강점을 가지고있다. 어쨌든 OP는 프로세스가 아닌 장치 드라이버 관련 정보를 묻습니다.
N
가 자식 프로세스 인 경우, pid 가 -family 함수 N
를 호출 할 때까지 pid가 여전히 동일한 프로세스를 참조 하도록 할 수 있습니다 wait
. 이렇게하면 인종이 없습니다.
/ proc 파일에서 읽을 때 커널은 해당 proc 파일에 대한 "읽기"기능으로 미리 등록 된 함수를 호출합니다. __proc_file_read
fs / proc / generic.c 의 기능을 참조하십시오 .
따라서 proc read의 안전성은 커널이 읽기 요청을 충족시키기 위해 호출하는 기능만큼 안전합니다. 해당 함수가 터치하는 모든 데이터를 올바르게 잠그고 버퍼에서 반환하면 해당 함수를 사용하여 읽는 것이 안전합니다. / proc / net / tcp에 대한 읽기 요청을 만족시키는 데 사용되는 것과 같은 proc 파일은 한동안 사용되어 왔으며 철저한 검토를 거쳤으므로 사용자가 요청할 수있는만큼 안전합니다. 실제로, 많은 일반적인 Linux 유틸리티는 proc 파일 시스템에서 읽고 다른 방식으로 출력 형식을 지정합니다. (머리 꼭대기에서 'ps'와 'netstat'가이를 수행한다고 생각합니다).
언제나 그렇듯이, 당신은 그것에 대해 나의 말을 할 필요가 없습니다. 당신은 당신의 두려움을 진정 소스를 볼 수 있습니다. proc_net_tcp.txt의 다음 문서는 / proc / net / tcp에 대한 "읽기"기능이 작동하는 위치를 알려주므로 해당 proc 파일에서 읽을 때 실행되는 실제 코드를보고 자신이 없는지 직접 확인할 수 있습니다 잠금 위험.
이 문서는 / proc / net / tcp 및 / proc / net / tcp6 인터페이스에 대해 설명합니다.
이 인터페이스는 tcp_diag를 위해 더 이상 사용되지 않습니다. 이 / proc 인터페이스는 현재 활성화 된 TCP 연결에 대한 정보를 제공하며 각각 net / ipv4 / tcp_ipv4.c의 tcp4_seq_show () 및 net / ipv6 / tcp_ipv6.c의 tcp6_seq_show ()에 의해 구현됩니다.