GNU/Linux >> Belajar Linux >  >> Linux

Apakah utas diimplementasikan sebagai proses di Linux?

Saya pikir ini bagian dari clone(2) halaman manual dapat menjernihkan perbedaan re. PID:

CLONE_THREAD (sejak Linux 2.4.0-test8)
Jika CLONE_THREAD disetel, anak ditempatkan di grup utas yang sama dengan proses pemanggilan.
Grup utas adalah fitur yang ditambahkan di Linux 2.4 untuk mendukung gagasan utas POSIX dari sekumpulan utas yang berbagi satu PID. Secara internal, PID yang dibagikan ini adalah apa yang disebut pengidentifikasi grup utas (TGID) untuk grup utas. Sejak Linux2.4, panggilan ke getpid(2) mengembalikan TGID pemanggil.

Frasa "utas diimplementasikan sebagai proses" mengacu pada masalah utas yang memiliki PID terpisah di masa lalu. Pada dasarnya, Linux awalnya tidak memiliki utas dalam suatu proses, hanya proses terpisah (dengan PID terpisah) yang mungkin memiliki beberapa sumber daya bersama, seperti memori virtual atau deskriptor file. CLONE_THREAD dan pemisahan ID proses dan ID utas membuat perilaku Linux lebih mirip sistem lain dan lebih seperti persyaratan POSIX dalam pengertian ini. Meskipun secara teknis OS masih belum memiliki implementasi terpisah untuk utas dan proses.

Penanganan sinyal adalah area bermasalah lainnya dengan implementasi lama, ini dijelaskan lebih detail di makalah yang dirujuk @FooF dalam jawaban mereka.

Seperti disebutkan dalam komentar, Linux 2.4 juga dirilis pada tahun 2001, tahun yang sama dengan bukunya, jadi tidak mengherankan jika beritanya tidak sampai ke cetakan itu.


Anda benar, memang "sesuatu pasti berubah antara tahun 2001 dan sekarang". Buku yang sedang Anda baca mendeskripsikan dunia menurut implementasi historis pertama dari utas POSIX di Linux, yang disebut LinuxThreads (lihat juga artikel Wikipedia untuk beberapa).

LinuxThreads memiliki beberapa masalah kompatibilitas dengan standar POSIX - misalnya utas yang tidak membagikan PID - dan beberapa masalah serius lainnya. Untuk memperbaiki kelemahan ini, implementasi lain yang disebut NPTL (Native POSIX Thread Library) dipelopori oleh Red Hat untuk menambahkan dukungan kernel dan ruang pengguna yang diperlukan perpustakaan untuk mencapai kepatuhan POSIX yang lebih baik (mengambil bagian yang baik dari proyek implementasi ulang lain yang bersaing oleh IBM yang disebut NGPT (" Utas Posix Generasi Selanjutnya"), lihat artikel Wikipedia tentang NPTL). Bendera tambahan ditambahkan ke clone(2) panggilan sistem (khususnya CLONE_THREAD itu @ikkkachu tunjukkan dalam jawabannya) mungkin merupakan bagian yang paling jelas dari modifikasi kernel. Bagian ruang pengguna dari karya tersebut akhirnya dimasukkan ke dalam Perpustakaan GNU C.

Masih saat ini beberapa SDK Linux tertanam menggunakan implementasi LinuxThreads lama karena mereka menggunakan versi footprint memori yang lebih kecil dari LibC yang disebut uClibc (juga disebut µClibc), dan butuh waktu bertahun-tahun sebelum implementasi ruang pengguna NPTL dari GNU LibC diporting dan dianggap sebagai implementasi threading POSIX default, karena secara umum platform khusus ini tidak berusaha untuk mengikuti mode terbaru dalam kecepatan kilat. Penggunaan implementasi LinuxThreads dalam operasi dapat diamati dengan memperhatikan bahwa, memang, PID untuk utas yang berbeda pada platform tersebut berbeda tidak seperti yang ditentukan oleh standar POSIX - seperti yang dijelaskan oleh buku yang sedang Anda baca. Sebenarnya, pernah Anda menelepon pthread_create() , Anda tiba-tiba meningkatkan jumlah proses dari satu menjadi tiga karena proses tambahan diperlukan untuk menjaga agar kekacauan tidak terjadi.

Halaman manual pthreads(7) Linux memberikan ikhtisar yang komprehensif dan menarik tentang perbedaan antara keduanya. Penjelasan lain yang mencerahkan, meskipun sudah ketinggalan zaman, tentang perbedaannya adalah makalah ini oleh Ulrich Depper dan Ingo Molnar tentang desain NPTL.

Saya menyarankan Anda untuk tidak menganggap bagian buku itu terlalu serius. Saya malah merekomendasikan utas POSIX Pemrograman Butenhof dan halaman manual POSIX dan Linux tentang subjek tersebut. Banyak tutorial tentang subjek yang tidak akurat.


Utas (Userspace) tidak diimplementasikan sebagai proses seperti itu di Linux, karena mereka tidak memiliki ruang alamat pribadi mereka sendiri, mereka masih berbagi ruang alamat dari proses induk.

Namun, utas ini diimplementasikan untuk menggunakan sistem akuntansi proses kernel, sehingga dialokasikan Thread ID (TID) mereka sendiri, tetapi diberi PID dan 'thread group ID' (TGID) yang sama sebagai proses induk - ini berbeda dengan fork, tempat TGID dan PID baru dibuat, dan TID-nya sama dengan PID.

Jadi tampaknya kernel baru-baru ini memiliki TID terpisah yang dapat ditanyakan, inilah yang berbeda untuk utas, cuplikan kode yang cocok untuk menunjukkan ini di masing-masing main() thread_function() di atas adalah:

    long tid = syscall(SYS_gettid);
    printf("%ld\n", tid);

Jadi seluruh kode dengan ini akan menjadi:

#include <pthread.h>                                                                                                                                          
#include <stdio.h>                                                                                                                                            
#include <unistd.h>                                                                                                                                           
#include <syscall.h>                                                                                                                                          

void* thread_function (void* arg)                                                                                                                             
{                                                                                                                                                             
    long tid = syscall(SYS_gettid);                                                                                                                           
    printf("child thread TID is %ld\n", tid);                                                                                                                 
    fprintf (stderr, "child thread pid is %d\n", (int) getpid ());                                                                                            
    /* Spin forever. */                                                                                                                                       
    while (1);                                                                                                                                                
    return NULL;                                                                                                                                              
}                                                                                                                                                             

int main ()                                                                                                                                                   
{                                                                                                                                               
    pthread_t thread;                                                                               
    long tid = syscall(SYS_gettid);     
    printf("main TID is %ld\n", tid);                                                                                             
    fprintf (stderr, "main thread pid is %d\n", (int) getpid ());                                                    
    pthread_create (&thread, NULL, &thread_function, NULL);                                           
    /* Spin forever. */                                                                                                                                       
    while (1);                                                                                                                                                
    return 0;                                                                                                                                                 
} 

Memberikan contoh keluaran dari:

main TID is 17963
main thread pid is 17963
thread TID is 17964
child thread pid is 17963

Linux
  1. Linux – Apakah Kernel Linux/unix yang Berbeda Dapat Dipertukarkan?

  2. Perintah Linux ps

  3. Pengantar Utas Linux – Bagian I

  1. Linux – Log Utas Sebelumnya Yang Sekarang Ditutup?

  2. Cara Membunuh Proses yang Berjalan di Linux

  3. Apakah utas kernel Linux benar-benar proses kernel?

  1. Temukan Proses Orphan Linux

  2. Apa itu Proses Linux, Utas, Proses Ringan, dan Status Proses

  3. Bagaimana cara mengetahui proses mana yang menggunakan ruang swap di Linux?