Jika utas berbagi PID yang sama, bagaimana mereka dapat diidentifikasi?

98

Saya memiliki pertanyaan terkait dengan implementasi utas di Linux.

Linux tidak memiliki dukungan utas eksplisit. Di ruang pengguna, kami mungkin menggunakan perpustakaan utas (seperti NPTL) untuk membuat utas. Sekarang jika kita menggunakan NPTL, ini mendukung pemetaan 1: 1.

Kernel akan menggunakan clone()fungsi tersebut untuk mengimplementasikan utas.

Misalkan saya telah membuat 4 utas. Maka itu berarti:

  • Akan ada 4 task_struct.
  • Di dalam task_struct, akan ada ketentuan untuk berbagi sumber daya sesuai argumen untuk kloning (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND).

Sekarang saya memiliki pertanyaan berikut:

  1. Apakah 4 utas akan memiliki PID yang sama? Jika seseorang dapat menjelaskan, bagaimana PID dibagikan.
  2. Bagaimana berbagai utas diidentifikasi; apakah ada konsep TID (thread ID)?
SPSN
sumber

Jawaban:

274

Keempat utas akan memiliki PID yang sama tetapi hanya jika dilihat dari atas. Apa yang Anda (sebagai pengguna) sebut sebagai PID bukanlah apa yang disebut kernel (lihat dari bawah) sebagai PID.

Di kernel, setiap utas memiliki ID sendiri, yang disebut PID (meskipun mungkin lebih masuk akal untuk menyebutnya TID, atau ID utas) dan mereka juga memiliki TGID (ID grup utas) yang merupakan PID utas yang memulai seluruh proses.

Sederhananya, ketika proses baru dibuat, itu muncul sebagai utas di mana PID dan TGID adalah nomor (baru) yang sama.

Saat utas memulai utas lain , utas yang dimulai itu mendapatkan PID-nya sendiri (sehingga penjadwal dapat menjadwalkannya secara independen) tetapi mewarisi TGID dari utas asli.

Dengan begitu, kernel dapat dengan senang hati menjadwalkan utas terlepas dari prosesnya, sementara proses (ID grup utas) dilaporkan kepada Anda.

Hierarki utas berikut mungkin membantu (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

Anda dapat melihat bahwa memulai proses baru (di sebelah kiri) memberi Anda PID baru dan TGID baru (keduanya diatur ke nilai yang sama), sementara memulai utas baru (di sebelah kanan) memberi Anda PID baru sambil mempertahankan yang sama TGID sebagai thread yang memulainya.


(a) Gemetar kagum pada keterampilan grafis saya yang mengesankan :-)

paxdiablo
sumber
20
FYI, getpid()mengembalikan tgid:, asmlinkage long sys_getpid(void) { return current->tgid;}seperti yang ditunjukkan di www.makelinux.com/
Duke
6
@Duke - wow, jadi itu sebabnya saya tidak bisa menemukan gettgid(2)fungsi. Dan getpid()tidak akan mengembalikan TID (thread "PID"), dan ada di mana gettid(2)masuk. Dengan cara ini saya bisa tahu, apakah kita berada di thread utama atau tidak.
Tomasz Gandor
2
Ini mengarah ke poin menarik lainnya: Jadi jika utas dan proses ditangani secara sama di dalam kernel (selain dari tgid), proses multi-utas pada akhirnya akan mendapatkan lebih banyak waktu CPU daripada satu utas, asalkan keduanya memiliki waktu yang sama prioritas dan tidak ada utas yang dihentikan karena alasan apa pun (seperti menunggu mutex).
Aconcagua
1
@Aconcagua, CFS (penjadwal yang benar-benar adil di Linux) umumnya bekerja seperti itu tetapi juga memungkinkan penggunaan ekstensi penjadwal grup untuk membuat keadilan beroperasi di seluruh kelompok tugas tertentu daripada tugas individu. Saya tidak pernah benar-benar memeriksanya selain dari pandangan sepintas.
paxdiablo
'' getpgrp '' untuk mendapatkan id grup
Pengcheng
2

Thread diidentifikasi menggunakan PID dan TGID (Thread group id). Mereka juga tahu utas mana yang merupakan induk dari yang pada dasarnya sebuah proses membagikan PID-nya dengan utas apa pun yang dimulai. ID Thread biasanya dikelola oleh perpustakaan thread itu sendiri (seperti pthread, dll ...). Jika 4 utas dimulai, mereka harus memiliki PID yang sama. Kernel itu sendiri akan menangani penjadwalan utas dan semacamnya tetapi pustaka adalah salah satu yang akan mengelola utas (apakah mereka dapat berjalan atau tidak tergantung pada penggunaan metode bergabung dan menunggu utas).

Catatan: Ini dari ingatan saya tentang kernel 2.6.36. Pekerjaan saya di versi kernel saat ini adalah di lapisan I / O jadi saya tidak tahu apakah sudah berubah sejak saat itu.

Yesus Ramos
sumber
-6

Linux menyediakan fork()panggilan sistem dengan fungsionalitas tradisional untuk menduplikasi suatu proses. Linux juga menyediakan kemampuan untuk membuat utas menggunakan clone()panggilan sistem. Namun, linux tidak membedakan antara proses dan utas.

SAUNDARYA KUMAR GUPTA
sumber