2015-11-26 18 views
6

Có ứng dụng .net đơn giản .exe. Vòng đời của nó là gì khi thực thi. Sự hiểu biết của tôi là những điều sau đây xảy ra:Vòng đời của ứng dụng .net

> 1. OS loads exe assemblies into memory 
> 2. OS checks if it is in fact .net assembly 
> 3. mscoree.dll loads, and loads CLR 
> 4. CLR takes over and loads external dlls, GC stuff, memory management etc. 
> 5. CLR creates app domain where exe assemblies are loaded 
> 6. exe is started 

Được nêu ở trên là chính xác (vui lòng giải thích), tôi quan tâm đến bước cuối cùng, khi lắp ráp CLR.

  1. Có bao nhiêu ngăn xếp, đống, chuỗi được tạo ?. Chủ đề có được tạo và thực thi mã trong tệp thi hành không?
  2. Kích thước bộ nhớ ban đầu được phân bổ là gì ?, ai phân bổ bộ nhớ (OS hoặc CLR?)
  3. Làm cách nào để biết bộ nhớ ban đầu cần bao nhiêu bộ nhớ?
  4. Nếu cần thêm bộ nhớ khi chạy exe, ai quyết định số lượng và thời điểm cấp phát bộ nhớ này?
  5. Điều gì sẽ xảy ra khi bạn đóng exe ?, CLR có chạy bất kỳ GC nào ngay trước khi dỡ Miền ứng dụng không? (đóng exe), hoặc hệ điều hành?
+5

Chỉ cần mua sách "CLR qua C#" hoặc đọc chuỗi blog "CLR Inside Out". Đây là cách quá rộng để trả lời đúng, và tôi khá chắc chắn mỗi câu hỏi của bạn đã được trả lời trước đó. – CodeCaster

Trả lời

1

Vâng, quá trình tự nó phức tạp hơn một chút so với bạn đã viết. Một số bước bao gồm nhiều hơn một bước có thể nghĩ - ví dụ, bước 1 và cách nạp PE (và bản thân mscoree.dll được tải) bao gồm các bước bên trong bên trong.

Nhưng, tôi sẽ cố gắng trả lời câu hỏi của bạn. Chỉ cần thông báo rằng các câu hỏi của bạn khá lớn, vì vậy tôi đã cố gắng trả lời chúng một thời gian ngắn. Tuy nhiên, nếu bạn thực sự quan tâm đến điều đó, tôi khuyên bạn nên đọc CLR qua C# (bởi Richter). Ông thảo luận về quá trình tải trong chương đầu tiên, và có chương dành riêng cho bộ thu gom rác.

Ngoài ra còn có một số bài viết MSDN tốt về nguyên tắc cơ bản của bộ thu gom rác mà bạn có thể thấy thú vị.

Có bao nhiêu ngăn xếp, đống, chuỗi được tạo ?. Chủ đề có được tạo và thực thi mã trong tệp thi hành không?

Ứng dụng bảng điều khiển đơn giản (trống) sẽ có 3 luồng: chủ đề chính, chủ đề GC và trình kết thúc. tất nhiên, mỗi luồng có một ngăn xếp riêng (1MB mỗi luồng).

Số lượng heaps phụ thuộc vào loại GC bạn đang sử dụng. Nếu bạn đang sử dụng Workstation GC (mặc định) sẽ có 1 vùng được quản lý (với 2 phân đoạn, một cho đối tượng "bình thường" và một là phân đoạn heap đối tượng lớn).

Nếu bạn đang làm việc với Server GC, sẽ có 1 đống cho mỗi lõi logic có sẵn trong hệ thống (mỗi một trong số các đống có hai phân đoạn).

kích thước của bộ nhớ ban đầu được phân bổ là gì ?, người phân bổ bộ nhớ (OS hoặc CLR?)

Bộ nhớ ban đầu bao gồm nhiều hơn một yếu tố: có 1MB ngăn xếp cho mỗi thread , có kích thước của hình ảnh được tải trong quá trình (tùy thuộc vào ứng dụng của bạn), và có yếu tố "động" của kích thước - phân bổ bạn đang tạo trong ứng dụng của mình, điều này khiến GC tăng kích thước heap, và các đối tượng bạn không sử dụng nữa được làm sạch bởi GC và có thể khiến GC giải phóng bộ nhớ.

Nếu cần thêm bộ nhớ khi chạy exe, ai sẽ quyết định số lượng và thời điểm cấp phát bộ nhớ này?

Nếu bạn có ứng dụng bảng điều khiển đơn giản, bên trong trường hợp chính bạn tạo của lớp mới. Trong trường hợp đó, từ khóa "mới" (lệnh CIL "newobj") sẽ làm cho CLR tính toán số lượng bộ nhớ cần thiết.

Nếu có đủ bộ nhớ trong thế hệ 0 (nơi đối tượng mới được lưu trữ), sẽ không có cấp phát bộ nhớ bổ sung. Nếu không có đủ bộ nhớ, GC sẽ khởi động và sẽ gọi VirtualAlloc để cấp phát bộ nhớ cho đối tượng. Tham chiếu cho đối tượng mới được tạo, trong kịch bản đó, sẽ được lưu trên ngăn xếp.

Tất nhiên, nơi tham chiếu được lưu (ngăn xếp, đống, thanh ghi bộ xử lý) và nơi các đối tượng được cấp phát (ngăn xếp/đống) có thể thay đổi. Về cơ bản, điều đó phụ thuộc nếu chúng ta đang nói về phân bổ lớp hoặc cấu trúc, và bối cảnh của phân bổ (nếu nó là phương thức bên trong, như một trường trong lớp khác, một trường trong cấu trúc, vv). Nó cũng có thể thay đổi dựa trên nền tảng.

Nếu cần thêm bộ nhớ khi chạy exe, ai sẽ quyết định số lượng và thời điểm cấp phát bộ nhớ này?

Tất cả cấp phát bộ nhớ cho đối tượng mới được tạo trong quy trình của bạn được CLR quản lý (tất nhiên CLR sử dụng Windows API như VirtualAlloc và VirtualFree và cửa sổ quản lý bộ nhớ ảo).

Khi bạn sử dụng toán tử "mới" để tạo đối tượng mới sẽ được tạo trong vùng được quản lý, CLR tính toán kích thước cần thiết để phân bổ (kích thước của tất cả các trường + phí nhỏ cần thiết để khóa đối tượng ob và biết nó là loại gì) và xem nếu có không gian có sẵn trong heap được quản lý (trong thế hệ 0, CLR luôn giữ một con trỏ đến nơi các đối tượng mới sẽ được phân bổ). Nếu có, nó sẽ sử dụng nó. nếu không, nếu không đủ bộ nhớ thì bộ sưu tập rác sẽ bắt đầu, và đôi khi (phụ thuộc vào trạng thái bộ nhớ sau quá trình gc và một số thứ khác) VirtualAlloc sẽ được CLR gọi để cấp phát bộ nhớ nhiều hơn cho quá trình.

Điều gì sẽ xảy ra khi bạn đóng exe ?, CLR có chạy bất kỳ GC nào ngay trước khi dỡ Miền ứng dụng không? (đóng exe), hoặc hệ điều hành?

CLR chạy nhanh GC trước khi dỡ bất kỳ miền ứng dụng nào. Mục đích của GC nhanh này là để cho phép hoàn thành một cơ hội để chạy. Khi đóng quá trình, không cần CLR làm sạch bộ nhớ, vì hệ điều hành vẫn làm như vậy.

Hy vọng điều đó sẽ hữu ích.

+0

# 3. Giả sử bạn có từ điển mới () trong mã, có phải chuỗi chính, (CLR), tài khoản cho điều đó ?, tăng kích thước của vùng heap? kích thước ban đầu của đống trước khi đọc dòng Dict mới là gì? – ShaneKm

+0

chỉnh sửa câu trả lời của tôi, hy vọng nó trả lời nó nhiều hơn một chút ... –

+0

* Nếu bạn đang làm việc với Server GC, sẽ có 1 đống cho mỗi chuỗi logic có sẵn trong hệ thống * Tôi giả sử bạn có nghĩa là một đống cho mỗi lõi logic. –

8

Có bao nhiêu ngăn xếp, đống, chuỗi được tạo?

Trong quá trình bạn áp dụng, có thể có nhiều chuỗi. Tuy nhiên, một trong số họ sẽ là chủ đề chính của việc thực thi.

Khi tạo chuỗi được phân bổ một ngăn xếp 1 MB.

người phân bổ bộ nhớ (OS hoặc CLR?)

Như được nêu here

garbage collector Bộ thực thi ngôn ngữ chung quản lý việc phân bổ và giải phóng bộ nhớ cho một ứng dụng

Đây là sự khác biệt đáng kể giữa quản lý và các chương trình không được quản lý. Nếu bạn đã lập trình trong cả hai C hoặc C++, bạn chắc chắn biết rằng trách nhiệm này thuộc về nhà phát triển chứ không phải cho người thu gom rác. Đó là một sức mạnh tuyệt vời. Nhưng với sức mạnh to lớn thì có trách nhiệm lớn lao. Bạn chịu trách nhiệm tìm kiếm (tạo) không gian bộ nhớ cần thiết. Sau đó, bạn phân bổ có đối tượng của bạn và khi bạn không cần nó nhiều hơn, bạn phải giải phóng bộ nhớ này. Bất kỳ sai lầm nào có thể thực hiện trong quy trình trên đều dẫn đến rò rỉ bộ nhớ và thậm chí là sự cố của chương trình của bạn. Hãy để một mình những khó khăn của xử lý sự cố một lỗi như thế này.

Mặt khác, trong thế giới của các chương trình được quản lý (C#, Java, JavaScript, v.v.), trách nhiệm này thuộc về một phần của thời gian chạy được gọi là bộ thu gom rác. Bộ thu gom rác phân bổ bộ nhớ và quyết định, khi nào là thời điểm thích hợp để khởi động và đổ rác. Điều này từ chính nó là một tiện ích tuyệt vời làm cho cuộc sống của nhà phát triển dễ dàng hơn đáng kể. Tuy nhiên đó là một sự cân bằng. Một chương trình được quản lý không thể đạt hiệu suất của một chương trình được quản lý tốt có cấu trúc.

Điều gì sẽ xảy ra khi bạn đóng exe ?, CLR có chạy bất kỳ quyền GC nào trước khi dỡ miền ứng dụng không? (đóng exe), hoặc hệ điều hành?

Khi bạn đóng một tệp thực thi, một trong những điều sẽ được thực hiện trước khi dỡ bỏ miền ứng dụng diễn ra, là một bộ sưu tập rác, theo bất kỳ tài nguyên nào được sử dụng sẽ được phát hành. Sau đó, miền ứng dụng sẽ được tải xuống. Sau này CLR sẽ được tách ra khỏi không gian bộ nhớ của quá trình và cuối cùng quá trình sẽ bị giết.

Các vấn đề liên quan