ESTABLISHED 상태 인 socket 에는 프로 세 스 정보 가 없습니다.
이 문 제 를 조사 할 때 저 는 먼저 netstat 를 사용 하여 커 널 프로 토 콜 스 택 의 연결 요청 이 프로 세 스 에 전달 되 지 않 았 는 지, 아니면 프로 세 스 accept 링크 가 느 렸 는 지, 아니면 recv 데이터 가 느 렸 는 지 확인 하고 다음 과 같이 기록 합 니 다.
netstat -anpl |grep -i 57372
tcp 0 0 127.0.0.1:57372 127.0.0.1:7010 ESTABLISHED 15044/curl
tcp 86 0 127.0.0.1:7010 127.0.0.1:57372 ESTABLISHED -
curl 에서 보 낸 요청 을 볼 수 있 습 니 다. 커 널 프로 토 콜 스 택 은 이미 받 아 들 였 지만 해당 하 는 링크 에 작은 세부 사항 이 있 습 니 다. 그것 은 바로 establishe 상태의 링크 입 니 다. 프로 세 스 번 호 를 찾 을 수 없습니다.
나 는 이전에 netstat 의 소스 코드 를 본 적 이 없다. 다만 strace 를 통 해 netstat 가 / proc / net / tcp (또는 / proc / net / tcp 6) 를 읽 고 링크 정 보 를 얻 는 것 을 대충 알 고 있 을 뿐이다.
cat /proc/net/tcp
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000:18A7 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 31915 1 ffff88057f2b9000 100 0 0 10 0
1: 0100007F:158E 00000000:0000 0A 00000000:00000000 00:00000000 00000000 2000 0 24924 1 ffff8800acf58000 100 0 0 10 0
2: 00000000:006F 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 9479 1 ffff880182c80000 100 0 0 10 0
3: 00000000:18B0 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 31914 1 ffff88057f2b8800 100 0 0 10 0
4: 017AA8C0:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 17065 1 ffff88056d3d8000 100 0 0 10 0
5: 00000000:0016 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 28681 1 ffff8802b8bd8000 100 0 0 10 0
6: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 26547 1 ffff88057f2b8000 100 0 0 10 0
7: 0100007F:0019 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 30024 1 ffff88058e678000 100 0 0 10 0
그러나 netstat - anpl 은 마지막 열 에 있 는 프로 세 스 정 보 를 어떻게 연결 하 는 지 잘 모 르 겠 습 니 다. netstat 소스 코드 를 다운로드 한 결과 순환 적 으로 / proc 아래 프로 세 스 를 옮 겨 다 니 는 것 을 발견 하고 / proc / 프로 세 스 / fd / xx 를 읽 습 니 다.
(gdb) p readlink(line, lname, sizeof(lname) - 1)
$34 = 14
(gdb) p lname
$35 = "socket:[31915]\000erfd]\000d\000\000\000\000\000\000\000"
그리고 extract 호출 을 통 해type_1_socket_위의 socket 을 분리 하 는 fd 는 31915. 읽 은 후에 해당 하 는 프로 세 스 와 프로 세 스 이름 을 포맷 한 다음 socket 의 inode 와 map 에 존재 합 니 다.
모든 / proc 의 프로 세 스 를 옮 겨 다 니 며 이 과정 이 너무 무 겁 습 니 다. map 가 존재 한 후 읽 기 를 통 해 /proc / net / tcp 에서 요구 에 부 합 된 socket 은 fd 의 숫자 를 맵 에 색인 하여 프로 세 스 번 호 를 찾 은 다음 인쇄 합 니 다.
Breakpoint 2, finish_this_one (uid=0, inode=31915, timers=0x7fffffffc010 "") at netstat.c:593
593 {
(gdb) bt
#0 finish_this_one (uid=0, inode=31915, timers=0x7fffffffc010 "") at netstat.c:593
#1 0x0000000000406eb7 in tcp_do_one (lnr=lnr@entry=1,
line=line@entry=0x7fffffffc190 " 0: 00000000:18A7 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 31915 1 ffff88057f2b9000 100 0 0 10 0", ' ' , "
", prot=prot@entry=0x41413f "tcp") at netstat.c:1056
#2 0x000000000040728f in tcp_info () at netstat.c:1061
#3 0x0000000000402956 in main (argc=2, argv=) at netstat.c:2172
(gdb) fr 1
#1 0x0000000000406eb7 in tcp_do_one (lnr=lnr@entry=1,
line=line@entry=0x7fffffffc190 " 0: 00000000:18A7 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 31915 1 ffff88057f2b9000 100 0 0 10 0", ' ' , "
", prot=prot@entry=0x41413f "tcp") at netstat.c:1056
1056 finish_this_one(uid,inode,timers);
(gdb) p line
$46 = 0x7fffffffc190 " 0: 00000000:18A7 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 31915 1 ffff88057f2 b9000 100 0 0 10 0", ' ' , "
"
(gdb) p inode
$47 = 31915
이 관련 원 리 를 알 게 된 후에 기본적으로 확인 할 수 있 습 니 다. 우리 응용 프로 세 스 는 제때에 accept 하지 않 았 습 니 다.
알 고 있 습 니 다. accept 의 호출 원 리 는 accept () - > sys 입 니 다.accept4() -> inet_accept() -> inet_csk_accept()
이 를 통 해 알 수 있 듯 이 accept 역할 은 이미 연 결 된 socket (즉 세 번 의 악 수 를 거 쳤 다) 으로 돌아 가 는 것 입 니 다. 이 과정 은 협의 스 택 과 비동기 적 입 니 다. accept () 는 직접 세 번 의 악수 과정 을 처리 하지 않 고 icsk 만 감청 합 니 다.accept_quue 대기 열, socket 이 세 번 악 수 를 하면 icsk 에 추 가 됩 니 다.accept_quue 에서 accept 가 해 야 할 일 은 대기 열 에 socket 을 삽입 한 다음 에 깨 워 서 이 socket 으로 돌아 가 는 것 입 니 다.세 번 악 수 를 하 는 과정 은 완전히 협의 창고 자체 가 완성 한 것 이다.
그래서 우 리 는 위의, 이미 established 된 링크 를 보 았 습 니 다. 업무 프로 세 스 가 제때에 accept 에 가지 않 아서 프로 세 스 와 관련 된 링크 를 볼 수 있 습 니 다.
막 힌 socket 에 대해 accept 는 기다 리 고 있 으 며 아래 에 있 습 니 다. sk_state_change 에서 깨어나다.
case TCP_SYN_RECV:
if (!acceptable)
return 1;
/* Once we leave TCP_SYN_RECV, we no longer need req
* so release it.
*/
if (req) {
synack_stamp = tcp_rsk(req)->snt_synack;
tp->total_retrans = req->num_retrans;
reqsk_fastopen_remove(sk, req, false);
} else {
synack_stamp = tp->lsndtime;
/* Make sure socket is routed, for correct metrics. */
icsk->icsk_af_ops->rebuild_header(sk);
tcp_init_congestion_control(sk);
tcp_mtup_init(sk);
tp->copied_seq = tp->rcv_nxt;
tcp_init_buffer_space(sk);
}
smp_mb();
tcp_set_state(sk, TCP_ESTABLISHED);// establish, , accept
sk->sk_state_change(sk);// sk sock, listen sk, sk->sk_wq
차단 되 지 않 은 socket 에 대해 서 는 poll 과 같은 비동기 수신 요청 함수 에서 listen socket 을 호출 하여 accept 연결 을 해 야 합 니 다.이 nginx 가 accept 링크 에 제때에 가지 않 은 이 유 는 호출 된 lua 모듈 에 큰 순환 이 생 겼 기 때 문 입 니 다.
결론:
1. netstat 를 사용 하지 마 세 요. 너무 무 겁 습 니 다. 여러분 은 반드시 ss 로 대체 해 야 합 니 다.
2. accept 호출 전에 established 상태 에 있 는 socket 의 inode 도 프로 세 스 와 관련 이 없습니다.
다음으로 전송:https://www.cnblogs.com/10087622blog/p/9362474.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.