Nếu các chủ đề chia sẻ cùng một PID, làm thế nào chúng có thể được xác định?


98

Tôi có một truy vấn liên quan đến việc triển khai các luồng trong Linux.

Linux không có hỗ trợ chuỗi rõ ràng. Trong không gian người dùng, chúng tôi có thể sử dụng thư viện luồng (như NPTL) để tạo luồng. Bây giờ nếu chúng ta sử dụng NPTL, nó hỗ trợ ánh xạ 1: 1.

Kernel sẽ sử dụng clone()hàm để thực hiện các luồng.

Giả sử tôi đã tạo 4 luồng. Sau đó, nó có nghĩa là:

  • Sẽ có 4 task_struct.
  • Bên trong task_struct, sẽ có cung cấp chia sẻ tài nguyên theo các đối số để sao chép (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND).

Bây giờ tôi có truy vấn sau:

  1. 4 chủ đề sẽ có cùng PID? Nếu ai đó có thể giải thích, các PID được chia sẻ như thế nào.
  2. Làm thế nào các chủ đề khác nhau được xác định; có một số khái niệm TID (ID chủ đề) không?

Câu trả lời:


274

Bốn luồng sẽ có cùng PID nhưng chỉ khi nhìn từ trên xuống. Cái mà bạn (với tư cách là người dùng) gọi là PID không phải là cái mà hạt nhân (nhìn từ bên dưới) gọi là PID.

Trong hạt nhân, mỗi luồng có ID riêng của nó, được gọi là PID (mặc dù có thể có ý nghĩa hơn nếu gọi đây là TID hoặc ID luồng) và chúng cũng có TGID (ID nhóm luồng) là PID của luồng. đã bắt đầu toàn bộ quá trình.

Nói một cách đơn giản, khi một quy trình mới được tạo, nó sẽ xuất hiện dưới dạng một chuỗi trong đó cả PID và TGID đều là cùng một số (mới).

Khi một luồng bắt đầu một luồng khác , luồng bắt đầu đó sẽ nhận PID của riêng nó (vì vậy bộ lập lịch có thể lên lịch cho nó một cách độc lập) nhưng nó kế thừa TGID từ luồng gốc.

Bằng cách đó, hạt nhân có thể lên lịch vui vẻ cho các luồng độc lập với tiến trình mà chúng thuộc về, trong khi các quy trình (ID nhóm luồng) được báo cáo cho bạn.

Hệ thống phân cấp các luồng sau đây có thể giúp (a) :

                      USER VIEW
 <-- PID 43 --> <----------------- PID 42 ----------------->
                     +---------+
                     | process |
                    _| pid=42  |_
                  _/ | tgid=42 | \_ (new thread) _
       _ (fork) _/   +---------+                  \
      /                                        +---------+
+---------+                                    | process |
| process |                                    | pid=44  |
| pid=43  |                                    | tgid=42 |
| tgid=43 |                                    +---------+
+---------+
 <-- PID 43 --> <--------- PID 42 --------> <--- PID 44 --->
                     KERNEL VIEW

Bạn có thể thấy rằng việc bắt đầu một quy trình mới (ở bên trái) cung cấp cho bạn PID mới TGID mới (cả hai đều được đặt thành cùng một giá trị), trong khi bắt đầu một chuỗi mới (ở bên phải) cung cấp cho bạn một PID mới trong khi vẫn duy trì TGID là chủ đề bắt đầu nó.


(a) Run lên vì kinh ngạc trước kỹ năng đồ họa ấn tượng của tôi :-)


20
FYI, getpid()trả về tgid:, asmlinkage long sys_getpid(void) { return current->tgid;}như được hiển thị trong www.makelinux.com/
Duke

6
@Duke - wow, đó là lý do tại sao tôi không thể tìm thấy một gettgid(2)hàm. Và getpid()nó sẽ không trả về TID ("PID" của chuỗi), và có ở đâu gettid(2). Bằng cách này, tôi có thể biết, nếu chúng ta đang ở trong chuỗi chính hay không.
Tomasz Gandor

2
Điều này dẫn đến một điểm thú vị khác: Vì vậy, nếu các luồng và quy trình được xử lý như nhau trong nhân (ngoại trừ tgid), thì quy trình đa luồng sẽ nhận được nhiều thời gian CPU hơn quy trình một luồng, miễn là cả hai đều có cùng ưu tiên và không có luồng nào bị tạm dừng vì bất kỳ lý do gì (chẳng hạn như chờ mutex).
Aconcagua

1
@Aconcagua, CFS (trình lập lịch hoàn toàn công bằng trong Linux) thường hoạt động theo cách đó nhưng cũng cho phép sử dụng các tiện ích mở rộng của trình lập lịch nhóm để làm cho sự công bằng hoạt động trên các nhóm nhiệm vụ nhất định thay vì các nhiệm vụ riêng lẻ. Tôi chưa bao giờ thực sự nhìn vào nó ngoài một cái nhìn lướt qua.
paxdiablo

'' getpgrp '' để lấy id nhóm
Pengcheng

2

Chủ đề được xác định bằng PID và TGID (Id nhóm luồng). Họ cũng biết luồng nào là cha của ai nên về cơ bản một quy trình chia sẻ PID của nó với bất kỳ luồng nào mà nó bắt đầu. ID luồng thường được quản lý bởi chính thư viện luồng (chẳng hạn như pthread, v.v.). Nếu 4 luồng được bắt đầu, chúng phải có cùng PID. Bản thân hạt nhân sẽ xử lý lập lịch luồng và như vậy nhưng thư viện là thư viện sẽ quản lý các luồng (liệu chúng có thể chạy hay không tùy thuộc vào việc bạn sử dụng các phương thức nối và chờ luồng).

Lưu ý: Đây là từ hồi ức của tôi về kernel 2.6.36. Công việc của tôi trong các phiên bản hạt nhân hiện tại là ở lớp I / O nên tôi không biết liệu điều đó có thay đổi kể từ đó hay không.


-6

Linux cung cấp lệnh fork()gọi hệ thống với chức năng truyền thống là sao chép một tiến trình. Linux cũng cung cấp khả năng tạo luồng bằng lệnh clone()gọi hệ thống Tuy nhiên, linux không phân biệt giữa các tiến trình và luồng.

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.