Câu trả lời:
mweerden: NT đã được thiết kế cho nhiều người dùng ngay từ ngày đầu tiên, vì vậy đây không thực sự là một lý do. Tuy nhiên, bạn nói đúng về việc tạo quy trình đóng một vai trò ít quan trọng hơn trên NT so với trên Unix vì NT, ngược lại với Unix, hỗ trợ đa luồng hơn đa xử lý.
Rob, đúng là fork tương đối rẻ khi sử dụng COW, nhưng trên thực tế, fork chủ yếu được theo sau bởi một người thực thi. Và một giám đốc điều hành cũng phải tải tất cả các hình ảnh. Do đó, thảo luận về hiệu suất của fork chỉ là một phần của sự thật.
Khi thảo luận về tốc độ tạo tiến trình, có lẽ nên phân biệt giữa NT và Windows / Win32. Theo như NT (tức là bản thân hạt nhân), tôi không nghĩ rằng việc tạo quy trình (NtCreateProcess) và tạo luồng (NtCreateThread) chậm hơn đáng kể so với Unix trung bình. Có thể còn một chút nữa đang diễn ra, nhưng tôi không thấy lý do chính cho sự khác biệt về hiệu suất ở đây.
Tuy nhiên, nếu bạn nhìn vào Win32, bạn sẽ nhận thấy rằng nó bổ sung khá nhiều chi phí cho quá trình tạo. Đầu tiên, nó yêu cầu CSRSS phải được thông báo về việc tạo quy trình, liên quan đến LPC. Nó yêu cầu ít nhất kernel32 phải được tải bổ sung và nó phải thực hiện một số mục công việc kế toán bổ sung cần được thực hiện trước khi quá trình này được coi là một quá trình Win32 chính thức. Và đừng quên về tất cả các chi phí bổ sung do phân tích cú pháp tệp kê khai, kiểm tra xem hình ảnh có yêu cầu miếng đệm tương thích hay không, kiểm tra xem các chính sách hạn chế phần mềm có áp dụng không, yada yada.
Điều đó nói rằng, tôi thấy sự chậm lại tổng thể trong tổng số tất cả những việc nhỏ phải được thực hiện ngoài việc tạo thô của một quy trình, không gian VA và luồng ban đầu. Nhưng như đã nói ở phần đầu - do ưa thích đa luồng hơn đa nhiệm, phần mềm duy nhất bị ảnh hưởng nghiêm trọng bởi chi phí bổ sung này là phần mềm Unix được chuyển tải kém. Mặc dù sơ đồ trang web này thay đổi khi phần mềm như Chrome và IE8 đột nhiên khám phá lại lợi ích của quá trình đa xử lý và bắt đầu thường xuyên khởi động và gỡ bỏ các quy trình ...
Unix có một lệnh gọi hệ thống 'fork' để 'chia nhỏ' quy trình hiện tại thành hai và cung cấp cho bạn một quy trình thứ hai giống với quy trình đầu tiên (mô đun trở lại từ cuộc gọi fork). Vì không gian địa chỉ của quy trình mới đã được thiết lập và việc chạy này sẽ rẻ hơn so với việc gọi 'CreateProcess' trong Windows và để nó tải hình ảnh exe, dlls liên quan, v.v.
Trong trường hợp rẽ nhánh, hệ điều hành có thể sử dụng ngữ nghĩa 'copy-on-write' cho các trang bộ nhớ được liên kết với cả hai quy trình mới để đảm bảo rằng mỗi quy trình nhận được bản sao của các trang mà họ sửa đổi sau đó.
Thêm vào những gì JP đã nói: phần lớn chi phí thuộc về khởi động Win32 cho quá trình này.
Nhân Windows NT thực sự hỗ trợ COW fork. SFU (môi trường UNIX của Microsoft dành cho Windows) sử dụng chúng. Tuy nhiên, Win32 không hỗ trợ fork. Quy trình SFU không phải là quy trình Win32. SFU là trực giao với Win32: cả hai đều là hệ thống con của môi trường được xây dựng trên cùng một hạt nhân.
Ngoài các lệnh gọi LPC ngoài quy trình tới CSRSS
, trong XP trở lên còn có lệnh gọi ngoài quy trình tới công cụ tương thích ứng dụng để tìm chương trình trong cơ sở dữ liệu tương thích ứng dụng. Bước này gây ra đủ chi phí mà Microsoft cung cấp tùy chọn chính sách nhóm để vô hiệu hóa công cụ tương thích trên WS2003 vì lý do hiệu suất.
Các thư viện thời gian chạy Win32 (kernel32.dll, v.v.) cũng thực hiện nhiều lần đọc và khởi tạo sổ đăng ký khi khởi động không áp dụng cho UNIX, SFU hoặc các quy trình gốc.
Các quy trình gốc (không có hệ thống con môi trường) được tạo rất nhanh. SFU thực hiện ít hơn Win32 rất nhiều trong việc tạo quy trình, vì vậy các quy trình của nó cũng được tạo nhanh.
CẬP NHẬT CHO NĂM 2019: thêm LXSS: Hệ thống con Windows cho Linux
Thay thế SFU cho Windows 10 là hệ thống con môi trường LXSS. Đây là chế độ hạt nhân 100% và không yêu cầu bất kỳ IPC nào mà Win32 tiếp tục có. Syscall cho các quy trình này được chuyển trực tiếp đến lxss.sys / lxcore.sys, do đó, fork () hoặc lệnh gọi tạo quy trình khác chỉ tốn tổng cộng 1 lần gọi hệ thống cho trình tạo. [Một vùng dữ liệu được gọi là phiên bản] theo dõi tất cả các quy trình, luồng và trạng thái thời gian chạy của LX.
Các quy trình LXSS dựa trên các quy trình gốc, không phải quy trình Win32. Tất cả những thứ cụ thể của Win32 như công cụ tương thích đều không được tham gia.
Ngoài câu trả lời của Rob Walker: Ngày nay bạn có những thứ như Thư viện chủ đề POSIX gốc - nếu bạn muốn. Nhưng trong một thời gian dài, cách duy nhất để "ủy quyền" công việc trong thế giới unix là sử dụng fork () (và nó vẫn được ưa chuộng trong nhiều trường hợp). ví dụ: một số loại máy chủ ổ cắm
socket_accept () cái nĩa() nếu (con) handleRequest () khác goOnBeingParent ()Do đó, việc triển khai fork phải nhanh chóng và rất nhiều tối ưu hóa đã được thực hiện theo thời gian. Microsoft xác nhận CreateThread hoặc thậm chí các sợi thay vì tạo các quy trình mới và sử dụng giao tiếp giữa các quy trình. Tôi nghĩ không "công bằng" khi so sánh CreateProcess với fork vì chúng không thể hoán đổi cho nhau. Có lẽ thích hợp hơn nếu so sánh fork / executive với CreateProcess.
Mấu chốt của vấn đề này là lịch sử sử dụng của cả hai hệ thống, tôi nghĩ. Windows (và DOS trước đó) ban đầu là hệ thống một người dùng cho máy tính cá nhân . Như vậy, các hệ thống này thường không phải tạo nhiều quy trình mọi lúc; (rất) nói một cách đơn giản, một quy trình chỉ được tạo ra khi một người dùng cô đơn này yêu cầu nó (và con người chúng ta hoạt động không nhanh lắm, nói một cách tương đối).
Các hệ thống dựa trên Unix ban đầu là hệ thống nhiều người dùng và máy chủ. Đặc biệt là đối với loại thứ hai, không có gì lạ khi có các quy trình (ví dụ: mail hoặc http daemon) tách các quy trình ra để xử lý các công việc cụ thể (ví dụ: chăm sóc một kết nối đến). Một yếu tố quan trọng để làm điều này là fork
phương pháp rẻ tiền (như Rob Walker ( 47865 ) đã đề cập , ban đầu sử dụng cùng một bộ nhớ cho quy trình mới được tạo) rất hữu ích vì quy trình mới ngay lập tức có tất cả thông tin mà nó cần.
Rõ ràng là ít nhất trong lịch sử, nhu cầu về các hệ thống dựa trên Unix để tạo quy trình nhanh là lớn hơn nhiều so với các hệ thống Windows. Tôi nghĩ điều này vẫn xảy ra bởi vì các hệ thống dựa trên Unix vẫn được định hướng theo quy trình, trong khi Windows, do lịch sử của nó, có lẽ đã được định hướng nhiều hơn (các luồng hữu ích để tạo các ứng dụng đáp ứng).
Tuyên bố từ chối trách nhiệm: Tôi hoàn toàn không phải là chuyên gia về vấn đề này, vì vậy hãy tha thứ cho tôi nếu tôi sai.
Uh, dường như có rất nhiều lời biện minh "tốt hơn là theo cách này" đang diễn ra.
Tôi nghĩ rằng mọi người có thể được hưởng lợi từ việc đọc "Showstopper"; cuốn sách về sự phát triển của Windows NT.
Toàn bộ lý do khiến các dịch vụ chạy dưới dạng DLL trong một quá trình trên Windows NT là chúng quá chậm như các quá trình riêng biệt.
Nếu bạn thất vọng và bẩn thỉu, bạn sẽ thấy rằng chiến lược tải thư viện là vấn đề.
Trên Unices (nói chung), các đoạn mã của Thư viện được chia sẻ (DLL) thực sự được chia sẻ.
Windows NT tải một bản sao của DLL cho mỗi quá trình, vì nó thao tác phân đoạn mã thư viện (và đoạn mã thực thi) sau khi tải. (Cho nó biết dữ liệu của bạn ở đâu?)
Điều này dẫn đến các đoạn mã trong thư viện không thể sử dụng lại được.
Vì vậy, quá trình tạo NT thực sự khá tốn kém. Và mặt trái, nó làm cho DLL không tiết kiệm đáng kể trong bộ nhớ, mà là cơ hội cho các vấn đề phụ thuộc giữa các ứng dụng.
Đôi khi, kỹ thuật phải trả giá khi lùi lại và nói, "bây giờ, nếu chúng ta định thiết kế cái này để thực sự hấp dẫn, nó sẽ trông như thế nào?"
Tôi đã từng làm việc với một hệ thống nhúng khá thất thường, và một ngày nọ nhìn vào nó và nhận ra đó là một magnetron trong khoang, với các thiết bị điện tử trong khoang vi sóng. Sau đó, chúng tôi đã làm cho nó ổn định hơn nhiều (và ít giống lò vi sóng hơn).
Kiến trúc Windows SW có một vài lớp và thành phần bổ sung không tồn tại trên Unix hoặc được đơn giản hóa và xử lý bên trong hạt nhân trên Unix.
Trên Unix, fork và execute là các lệnh gọi trực tiếp đến hạt nhân.
Trên Windows, kernel API không được sử dụng trực tiếp, có win32 và một số thành phần khác nằm trên nó, vì vậy quá trình tạo quy trình phải đi qua các lớp bổ sung và sau đó quy trình mới phải khởi động hoặc kết nối với các lớp và thành phần đó.
Trong một thời gian khá lâu, các nhà nghiên cứu và tập đoàn đã cố gắng phá vỡ Unix theo một cách khá giống nhau, thường dựa trên các thí nghiệm của họ trên nhân Mach ; một ví dụ nổi tiếng là OS X. . Tuy nhiên, mỗi khi họ cố gắng, nó trở nên chậm đến mức họ kết thúc ít nhất một phần hợp nhất các mảnh trở lại hạt nhân vĩnh viễn hoặc cho các lô hàng sản xuất.
Vì dường như có một số biện minh về MS-Windows trong một số câu trả lời, ví dụ:
Dữ liệu được tổng hợp từ http://www.bitsnbites.eu/benchmarking-os-primaries/ .
Bởi vì sự thiên vị là không thể tránh khỏi, khi tóm tắt, tôi đã làm điều đó có lợi cho Phần cứng MS-Windows
cho hầu hết các bài kiểm tra i7 8 nhân 3.2GHz. Ngoại trừ Raspberry-Pi chạy Gnu / Linux
Lưu ý: Trên linux, fork
nhanh hơn là phương pháp ưa thích của MS-Window CreateThread
.
Theo thứ tự tốc độ, nhanh nhất đến chậm nhất (số là thời gian, càng nhỏ càng tốt).
Tất cả những điều đó cộng với thực tế là trên máy Win có lẽ phần mềm chống vi-rút sẽ hoạt động trong quá trình CreateProcess ... Đó thường là sự chậm chạp lớn nhất.
Cũng cần lưu ý rằng mô hình bảo mật trong Windows phức tạp hơn nhiều so với các hệ điều hành dựa trên unix, điều này làm tăng thêm rất nhiều chi phí trong quá trình tạo. Tuy nhiên, một lý do khác tại sao đa luồng được ưa thích hơn đa xử lý trong Windows.
fork()