Chủ đề so với quy trình (Ngã ba)


9

Các ứng dụng Linux thường phân nhánh sau đó thực thi (với execve ()), nhưng các ứng dụng Java và một số MPM Apache nhất định sử dụng luồng. Nếu forking, sử dụng fork + exec để sinh ra một tiến trình, phiên bản cấp cao để phân luồng là gì? Làm thế nào để JVM hoặc Worker MPM chủ đề sinh sản?


2
Kiểm tra Stackoverflow. Có một số câu hỏi và trả lời đã giải thích một phần về điều này.
Henk Langeveld

Câu trả lời:


13

Ý tưởng đằng sau các luồng và các tiến trình là như nhau: Bạn rẽ nhánh đường dẫn thực thi. Mặt khác, các luồng và các tiến trình khác nhau trong những thứ như bộ nhớ. Các quy trình có không gian VM khác nhau trong khi các luồng chia sẻ bất cứ điều gì tồn tại trước khi phân tách.

Hiểu rõ cả việc phân luồng và chuyển công việc bằng cách sử dụng lệnh gọi clone () (man 2 clone):

Không giống như fork (2), clone () cho phép tiến trình con chia sẻ các phần của bối cảnh thực thi của nó với quá trình gọi, chẳng hạn như không gian bộ nhớ, bảng mô tả tệp và bảng xử lý tín hiệu. (Lưu ý rằng trên trang thủ công này, "quy trình gọi" thường tương ứng với "quy trình cha mẹ". Nhưng hãy xem mô tả của CLONE_PARENT bên dưới.)

Công dụng chính của clone () là để thực hiện các luồng: nhiều luồng điều khiển trong một chương trình chạy đồng thời trong một không gian bộ nhớ dùng chung.

Sự khác biệt đến từ các cờ được truyền cho clone (). Như bạn có thể thấy từ trang man, fork và luồng chỉ là một tập hợp các tham số được xác định trước để sao chép (). Tuy nhiên người ta cũng có thể làm công cụ tùy chỉnh với nó.


1
Uhm? Gì? Vui lòng đọc lại gần như mọi cuốn sách về chủ đề này, bởi vì không gian bộ nhớ riêng cho các quy trình là một vấn đề lớn. Cũng giúp "bắt" mã gặp sự cố, trong khi đó kernel sẽ đơn giản giết chết một tiến trình trong đó một luồng riêng lẻ đi theo dây / trespasses.
0xC0000022L

3
@ 0xC0000022L đối số của bạn không mâu thuẫn với câu trả lời, vì dường như đối với tôi.
Ruslan

1
@Ruslan: Tôi xin khác biệt: "Ý tưởng [...] là giống nhau"? Ý tưởng đằng sau các chủ đề thực sự là đồng thời, nhưng đối với các quy trình thì đây là một câu chuyện hoàn toàn khác.
0xC0000022L

4
@ 0xC0000022L Bạn đã bỏ lỡ phần quan trọng trong câu trả lời của V13: "Bạn rẽ nhánh đường thực thi" - câu hỏi là về cách các luồng được sinh ra, chứ không phải sự khác biệt giữa các luồng và quy trình là gì
Izkata

@Izkata: hoàn toàn không. Tôi chỉ cho rằng đây không phải là một yêu cầu chính xác.
0xC0000022L

8

Hầu hết các hệ điều hành đa hệ điều hành (HĐH) không sử dụng Unix đều sử dụng lệnh gọi "spawn ()" hoặc một cái gì đó tương tự để tạo ra một quy trình hoặc luồng điều khiển hệ điều hành mới. Spawn () có xu hướng là một cuộc gọi rất phức tạp, với rất nhiều tùy chọn và rất nhiều chi phí. Một trong những đổi mới của Unix là cung cấp cách thức tạo ra các quy trình thấp hơn nhiều - fork (). Unix đã xử lý nhiều tùy chọn cần thiết để sinh ra () bằng cách cho phép số lượng xử lý tùy ý trước nửa còn lại của spawn (), với exec ().

Khi Unix và các biến thể của chúng được sử dụng ngày càng nhiều, việc tạo quy trình trên không thấp đã được tìm thấy là hữu ích và đã được sử dụng. Trên thực tế, nó đã được sử dụng rất nhiều, đến nỗi mọi người muốn các cách thậm chí thấp hơn để tạo ra các quy trình, và do đó, ý tưởng về "các luồng" đã ra đời. Ban đầu, các luồng được xử lý hoàn toàn bởi quá trình khởi tạo (và các chương trình như JVM có thể thực hiện việc này với "các luồng xanh"); nhưng xử lý lập lịch đa luồng là khó khăn và thường được thực hiện không chính xác. Vì vậy, có một cách dễ dàng hơn, thực hiện các luồng trung gian, trong đó HĐH xử lý lập lịch nhưng một số chi phí được lưu bằng cách (thường) chia sẻ không gian địa chỉ giữa các luồng.

Câu hỏi của bạn rất khó trả lời vì có một số khái niệm khác nhau nhưng có liên quan là tất cả "chủ đề" và để biết chi tiết, bạn cần một tính từ để mô tả cái nào bạn đang tham khảo. Mặt khác, hiểu được sự khác biệt có thể sẽ dẫn bạn đến câu trả lời cụ thể mà bạn muốn. Tra cứu những thứ như "quy trình nhẹ", "chủ đề người dùng" và "rfork ()" để biết thêm thông tin.


1
"Xử lý lập lịch đa luồng là khó khăn và thường được thực hiện không chính xác" cần trích dẫn. Việc thực hiện các luồng không gian người dùng không phải là một vấn đề. Vấn đề với các luồng không gian người dùng là nếu một luồng thực hiện chặn tòa nhà thì tất cả các luồng sẽ bị chặn. Cách duy nhất để tránh điều này là sử dụng các luồng cấp hệ thống.
Bakuriu

1
Thật thú vị, Windows không bao gồm sự đổi mới này của Unix: nó có CreateProcess()nhưng không có gì tương tự fork().
Ruslan

2
@Bakuriu - tìm kiếm bất kỳ bài viết nào trong số nhiều bài viết về xây dựng lịch trình đa xử lý, duy trì sự công bằng, tránh chết đói, xử lý các ưu tiên, v.v. Việc triển khai các luồng không gian người dùng không phải là vấn đề. Lên lịch các ví dụ không tầm thường là khó khăn.
mpez0

@Ruslan: người ta có thể rẽ nhánh trên Windows, nó không phải là một phần của API Win32. Đọc "API bản địa Windows NT / 2000" của Nebbett. Ông có một thực hiện bắt chước fork().
0xC0000022L

3

Chủ đề và forking thực sự là hai khái niệm khác nhau, cả hai đều tồn tại trong các hệ thống Unix / Linux (và cả hai đều có thể được sử dụng trong C / C ++).

Ý tưởng về một fork () về cơ bản là tạo ra một quy trình riêng biệt có cùng mã thực thi với quy trình cha và bắt đầu thực hiện tại dòng ngã ba. Mục đích của việc sử dụng các nhánh với các hàm exec là các hàm exec sẽ đóng quá trình gọi chúng khi chúng kết thúc. Vì vậy, bạn thường rẽ nhánh, nhận được PID của mỗi quá trình (đứa trẻ luôn là 0) và khiến cha mẹ đợi cho đến khi đứa trẻ hoàn thành việc thực hiện chức năng exec.

Chủ đề được sử dụng cho song song (nhớ lại rằng cha mẹ chờ đợi đứa trẻ, thông thường, trong một chương trình rẽ nhánh). Một chuỗi, chẳng hạn như pthread trong C / C ++ (thực hiện tìm kiếm Google), sẽ chạy song song với quy trình chính và có thể chia sẻ các biến toàn cục và các hàm toàn cầu với chương trình gốc. Vì các luồng Java hoạt động tương tự nhau, tôi sẽ tưởng tượng rằng chúng hoạt động giống như các luồng này hơn là quá trình rèn.

Về cơ bản, có một sự khác biệt giữa forking và luồng. Họ làm những việc khác biệt (mặc dù có vẻ giống nhau). Những khái niệm này có thể khó hiểu, nhưng bạn có thể tìm hiểu chúng thông qua nghiên cứu (mở rộng) nếu bạn có mong muốn trung thực để hiểu chúng.

EDIT # 1

Xin vui lòng xem các ví dụ về cách dĩa và chủ đề có thể được gọi và sử dụng. Xin lưu ý hành vi của các hàm exec và tác dụng của chúng trên chương trình chính.

http://www.jdembrun.com:4352/computerScience/forkVSthread.zip


2
Fork (có hoặc không có exec) cũng có thể được sử dụng cho song song. Tôi không chắc ý của bạn là gì khi "hàm exec đóng quy trình gọi chúng khi chúng kết thúc", exec thực hiện xong khi chạy xong khi quá trình kết thúc. Cũng pthreadlà một API, không phải là một triển khai luồng.
Mat

Về vấn đề ngã ba, tôi đang trích dẫn giáo viên hệ điều hành của mình. Theo những gì anh ấy đã nói với chúng tôi, vâng, forking có thể được sử dụng để chạy song song, nhưng, nếu nó sử dụng một hàm exec, đó sẽ là cái cuối cùng. Đối với pthread, nó có nghĩa là một ví dụ.
jaredad7

Exec sẽ là cuộc gọi cuối cùng trong mã của người gọi, không phải là hướng dẫn cuối cùng của quá trình rẽ nhánh. Quá trình rẽ nhánh sẽ tiếp tục chạy mã exec'd.
Mat

Nhận xét của bạn đã nhắc tôi kiểm tra những điều này. Tôi đã viết một số chương trình c ++ thể hiện hành vi của các hàm exec và tác dụng của chúng đối với các chương trình khi được sử dụng trong forks so với thread. Xin vui lòng xem chỉnh sửa ở trên.
jaredad7

Tôi sợ hầu hết mọi người sẽ không bận tâm để tải về điều đó. Ngoài ra, các ví dụ của bạn không minh họa sự khác biệt thú vị giữa các mô hình, chủ yếu liên quan đến việc chia sẻ (hoặc không) không gian địa chỉ.
Mat

1

Cả JVM và Apache MPM đều dựa vào kernel cho các luồng gốc. Đó là, họ sử dụng HĐH để lên lịch cho họ. Tất nhiên cả hai đều cần API riêng để theo dõi nội dung.

Stackoverflow đã có một số câu hỏi liên quan đến điều này:

  1. Chủ đề gốc JVM , kiểm tra câu trả lời này để biết thêm chi tiết.

  2. Apache có hai loại MPM: Prefork, với một tiến trình cho mỗi luồng và Worker, xử lý nhiều luồng: MPM của Apache . Kiểm tra các tài liệu tham khảo đểcodebucket


1

Nếu forking, sử dụng fork + exec để sinh ra một tiến trình, phiên bản cấp cao để phân luồng là gì? Làm thế nào để JVM hoặc Worker MPM chủ đề sinh sản?

Đó là nền tảng cụ thể, nhưng trên linux và tôi sẽ cho rằng nhiều hệ thống tuân thủ POSIX khác họ sử dụng triển khai cục bộ của pthreads , API luồng luồng người dùng. Ví dụ:

#include <pthread.h>

pthread_t tid;
pthread_create(&tid, NULL, somefunc, NULL);

Bắt đầu một luồng mới gọi somefunclà điểm thực hiện đầu tiên của nó.

Bạn cũng có thể tạo các luồng - khác với các nhánh trong đó chúng có chung không gian bộ nhớ heap toàn cầu của tiến trình cha, thay vì nhận một bản sao của nó (nhưng lưu ý các luồng thực hiện với một bộ nhớ ngăn xếp độc lập của riêng chúng) - với clone()cuộc gọi hệ thống, đó là những gì pthreads được xây dựng trên đầu trang.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.