NSThread 의 main 메소드 내부에는 어떤 것들이 있습니까?

8322 단어
NSThread에서 start 메서드를 호출하면 start 메서드는 main 메서드를 호출합니다.그럼 이 메일 방법 내부에 뭘 했죠?다음은 어셈블리 코드입니다.
 1 ;Foundation`-[NSThread main]:
 2 ->  0x7fff2594fa69 0>:  push   rbp
 3     0x7fff2594fa6a 1>:  mov    rbp, rsp
 4     0x7fff2594fa6d 4>:  mov    rax, qword ptr [rdi + 0x8]
 5     0x7fff2594fa71 8>:  mov    rsi, qword ptr [rax + 0x20]
 6     0x7fff2594fa75 12>: test   rsi, rsi
 7     0x7fff2594fa78 15>: je     0x7fff2594fa8e            ; 
 8     0x7fff2594fa7a 17>: mov    rdi, qword ptr [rax + 0x18]
 9     0x7fff2594fa7e 21>: test   rdi, rdi
10     0x7fff2594fa81 24>: je     0x7fff2594fa8e            ; 
11     0x7fff2594fa83 26>: mov    rdx, qword ptr [rax + 0x28]
12     0x7fff2594fa87 30>: pop    rbp
13     0x7fff2594fa88 31>: jmp    qword ptr [rip + 0x5b02d3c2] ; (void *)0x00007fff50ba4400: objc_msgSend
14     0x7fff2594fa8e 37>: pop    rbp
15     0x7fff2594fa8f 38>: ret  

rdi 레지스터가 저장된 것이self이기 때문에 우리는 4줄의 어셈블리가 현재 NSThread 대상에서 8바이트를 옮기고 이 주소가 가리키는 값을 rax 레지스터에 전달하는 것이 NSThread 대상 내부의 실례적인 변수 값을 얻는 것임을 알 수 있다.그렇다면 NSThread 객체 내부에서 8바이트 오프셋된 인스턴스 변수는 무엇입니까?NSThread 객체 내부의 인스턴스 변수는 다음과 같은 방법으로 가져옵니다.
1 (lldb) po [0x600002bbe600 _ivarDescription]
2 <NSThread: 0x600002bbe600>:
3 in NSThread:
4     _private (id): <_NSThreadData: 0x600000fe0a00>
5     _bytes (unsigned char[44]): Value not representable, [44C]
6 in NSObject:
7     isa (Class): NSThread (isa, 0x7fff87b504c8)

위의 출력에서 볼 수 있듯이 NSThread 대상 내부의 실례 변수는 3개이고 편향 8바이트는 하나의 이사 바늘의 길이이다. 그러면 이때의 실례 변수는 위에서 출력한 4줄의 이다NSThreadData 객체, 즉 rax 레지스터는 지금 입니다.NSThreadData 객체의 주소입니다.
계속main의 인코딩 5줄을 보십시오. 이 줄 인코딩 은NSThreadData 객체 오프셋 32바이트의 인스턴스 변수 값은 rsi 레지스터에 지정됩니다.마찬가지로, 우리가 보기엔NSThreadData 객체 오프셋 32바이트의 인스턴스 변수는 무엇입니까?
 1 po [0x600000fe0a00 _ivarDescription]
 2 <_NSThreadData: 0x600000fe0a00>:
 3 in _NSThreadData:
 4     dict (id): <__NSDictionaryM: 0x600003edaa80>
 5     name (id): @"com.apple.uikit.eventfetch-thread"
 6     target (id): <UIEventFetcher: 0x6000001fc000>
 7     selector (SEL): threadMain
 8     argument (id): nil
 9     seqNum (int): 2
10     qstate (unsigned char): Value not representable, C
11     qos (char): 33
12     cancel (unsigned char): Value not representable, C
13     status (unsigned char): Value not representable, C
14     performQ (id): nil
15     performD (NSMutableDictionary*): nil
16     attr (struct _opaque_pthread_attr_t): {
17         __sig (long): 1414022209
18         __opaque (char[56]): Value not representable, [56c]
19     }
20     tid (struct _opaque_pthread_t*): 0x600000fe0a88 -> 0x700004e45000
21     pri (double): 0.5
22     defpri (double): 0.5
23 in NSObject:
24     isa (Class): _NSThreadData (isa, 0x7fff87b504a0)

위의 출력을 통해 우리는 32 바이트의 편이가 selector의 실례 변수라는 것을 발견했다. (편이를 계산할 때 이사 바늘을 잊지 마라.) 즉, 현재rsi 레지스터 안에 selector의 값이 있다는 것이다.
main 함수 어셈블리 6행은 selector가 비어 있는지 확인하고 비어 있으면 전용 줄로 이동합니다. 즉, 인코딩 14행입니다. 이때main 함수가 창고를 지우면 종료됩니다.만약 selector에 값이 있다면,NSThreadData 객체가 24바이트 오프셋된 인스턴스 변수는 rdi 레지스터(8행)에 전달됩니다.위의 출력을 대조하면 rdi 레지스터의 값은 target 실례 변수 값이어야 합니다.9번째 줄 인코딩은 target이 비어 있는지 확인하고 빈 함수도 종료합니다.비어있지 않으면NSThreadData 대상은 40바이트의 실례 변수를 rdx 레지스터에 전송합니다. 이 때 rdx 레지스터는 argument 실례 변수의 값을 저장합니다.target이 생기고,selector가 생기고,argument가 생기면,코딩 13줄에서objc 를 호출합니다msgSend 이 방법은 [targetselector:argument]를 호출하고 실행이 끝난 후main 함수를 종료합니다.
 
요약:
1 NSThread를 만들 때 target이나 selector를 지정하지 않으면main 함수가 바로 출시됩니다.
2 모두 지정하면main 함수는 [target selector:argument]를 호출하여 실행이 끝난 후에 종료합니다

좋은 웹페이지 즐겨찾기