Baru-baru ini, saya telah ditanya pertanyaan dalam wawancara apa perbedaan antara proses dan utas. Sungguh, saya tidak tahu jawabannya. Saya berpikir sejenak dan memberikan jawaban yang sangat aneh.
Thread berbagi memori yang sama, proses tidak. Setelah menjawab ini, pewawancara memberi saya senyum jahat dan mengajukan pertanyaan berikut kepada saya:
P. Apakah Anda tahu segmen di mana suatu program dibagi?
Jawaban saya: ya (pikir itu mudah) Stack, Data, Code, Heap
Q. Jadi, beri tahu saya: segmen mana yang dibagikan thread?
Saya tidak bisa menjawab ini dan akhirnya mengatakan semuanya.
Tolong, bisakah ada yang menyajikan jawaban yang benar dan mengesankan untuk perbedaan antara proses dan utas?
Jawaban:
Anda benar, tetapi utas membagikan semua segmen kecuali tumpukan. Utas memiliki susunan panggilan independen, namun memori di susunan utas lainnya masih dapat diakses dan secara teori Anda dapat menahan pointer ke memori dalam kerangka tumpukan lokal beberapa utas lainnya (meskipun Anda mungkin harus menemukan tempat yang lebih baik untuk meletakkan memori itu!).
sumber
Dari Wikipedia (saya pikir itu akan menjadi jawaban yang sangat bagus untuk pewawancara: P)
sumber
Sesuatu yang benar-benar perlu ditunjukkan adalah bahwa sebenarnya ada dua aspek untuk pertanyaan ini - aspek teoritis dan aspek implementasi.
Pertama, mari kita lihat aspek teoretisnya. Anda perlu memahami apa proses secara konseptual untuk memahami perbedaan antara proses dan utas dan apa yang dibagikan di antara mereka.
Kami memiliki yang berikut dari bagian 2.2.2 Model Thread Klasik dalam Sistem Operasi Modern 3e oleh Tanenbaum:
Dia melanjutkan:
Lebih jauh ke bawah ia menyediakan tabel berikut:
Di atas adalah apa yang Anda butuhkan agar thread dapat berfungsi. Seperti yang telah ditunjukkan orang lain, hal-hal seperti segmen adalah detail implementasi tergantung OS.
sumber
Beri tahu pewawancara bahwa itu sepenuhnya tergantung pada implementasi OS.
Ambil Windows x86 misalnya. Hanya ada 2 segmen [1], Kode dan Data. Dan keduanya dipetakan ke seluruh ruang alamat 2GB (linier, pengguna). Basis = 0, Batas = 2GB. Mereka akan membuat satu tetapi x86 tidak memungkinkan segmen menjadi Baca / Tulis dan Jalankan. Jadi mereka membuat dua, dan mengatur CS untuk menunjuk ke deskriptor kode, dan sisanya (DS, ES, SS, dll) untuk menunjuk ke yang lain [2]. Namun keduanya menunjuk ke hal yang sama!
Orang yang mewawancarai Anda telah membuat asumsi tersembunyi bahwa ia tidak menyatakannya, dan itu adalah trik bodoh untuk ditarik.
Jadi tentang
Segmen tidak relevan dengan pertanyaan, setidaknya di Windows. Utas berbagi seluruh ruang alamat. Hanya ada 1 tumpukan segmen, SS, dan itu menunjuk ke hal-hal yang sama persis seperti yang dilakukan DS, ES, dan CS [2]. Yaitu seluruh ruang pengguna berdarah . 0-2GB. Tentu saja, itu tidak berarti utas hanya memiliki 1 tumpukan. Biasanya masing-masing memiliki tumpukan sendiri, tetapi segmen x86 tidak digunakan untuk tujuan ini.
Mungkin * nix melakukan sesuatu yang berbeda. Siapa tahu. Premis yang mendasari pertanyaan itu rusak.
ntsd notepad
:cs=001b ss=0023 ds=0023 es=0023
sumber
Secara umum, Thread disebut proses ringan. Jika kita membagi memori menjadi tiga bagian maka akan menjadi: Kode, data, dan Stack. Setiap proses memiliki bagian kode, data, dan tumpukan sendiri dan karena konteks ini, waktu sakelar agak tinggi. Untuk mengurangi waktu switching konteks, orang telah datang dengan konsep utas, yang membagi data dan segmen kode dengan utas / proses lain dan memiliki segmen STACK sendiri.
sumber
Suatu proses memiliki kode, data, tumpukan dan tumpukan segmen. Sekarang, Instruction Pointer (IP) dari utas atau utas menunjuk ke segmen kode dari proses. Segmen data dan tumpukan dibagi oleh semua utas. Sekarang bagaimana dengan area stack? Apa sebenarnya area tumpukan? Ini adalah area yang dibuat oleh proses hanya untuk menggunakan utasnya ... karena tumpukan dapat digunakan dengan cara yang jauh lebih cepat daripada tumpukan dll. Area tumpukan proses dibagi di antara utas, yaitu jika ada 3 utas, maka tumpukan area dari proses dibagi menjadi 3 bagian dan masing-masing diberikan kepada 3 utas. Dengan kata lain, ketika kita mengatakan bahwa setiap utas memiliki tumpukan sendiri, tumpukan itu sebenarnya merupakan bagian dari area tumpukan proses yang dialokasikan untuk setiap utas. Ketika sebuah utas menyelesaikan eksekusi, tumpukan utas tersebut direklamasi oleh proses. Faktanya, tidak hanya tumpukan proses yang dibagi di antara utas, tetapi semua set register yang menggunakan thread seperti SP, PC dan register negara adalah register dari proses. Jadi ketika harus berbagi, kode, data, dan area tumpukan dibagi, sedangkan area tumpukan hanya dibagi di antara utas.
sumber
Thread berbagi kode dan segmen data dan heap, tetapi mereka tidak membagikan stack.
sumber
Thread berbagi data dan kode sementara proses tidak. Tumpukan tidak dibagi untuk keduanya.
Proses juga dapat berbagi memori, lebih tepatnya kode, misalnya setelah a
Fork()
, tetapi ini adalah detail implementasi dan (sistem operasi) optimasi. Kode yang dibagikan oleh banyak proses akan (mudah-mudahan) menjadi duplikat pada penulisan pertama ke kode - ini dikenal sebagai copy-on-write . Saya tidak yakin tentang semantik yang tepat untuk kode utas, tetapi saya menganggap kode yang dibagikan.1 Kode ini secara logis pribadi tetapi mungkin bersama untuk alasan kinerja. 2 Saya tidak yakin 100%.
sumber
Threads membagikan semuanya [1]. Ada satu ruang alamat untuk seluruh proses.
Setiap utas memiliki tumpukan dan registernya sendiri, tetapi semua tumpukan utas terlihat di ruang alamat bersama.
Jika satu utas mengalokasikan beberapa objek pada tumpukannya, dan mengirimkan alamat ke utas lain, keduanya akan memiliki akses yang sama ke objek tersebut.
Sebenarnya, saya baru saja memperhatikan masalah yang lebih luas: Saya pikir Anda membingungkan dua penggunaan segmen kata .
Format file untuk yang dapat dieksekusi (mis., ELF) memiliki bagian yang berbeda di dalamnya, yang dapat disebut sebagai segmen, yang berisi kode kompilasi (teks), data yang diinisialisasi, simbol tautan, info debug, dll. Tidak ada segmen tumpukan atau tumpukan di sini, karena itu hanya konstruksi runtime.
Segmen file biner ini dapat dipetakan ke dalam ruang alamat proses secara terpisah, dengan izin yang berbeda (mis. Read-only executable untuk kode / teks, dan copy-on-write yang tidak dapat dieksekusi untuk data yang diinisialisasi).
Area ruang alamat ini digunakan untuk tujuan yang berbeda, seperti alokasi tumpukan dan tumpukan utas, berdasarkan konvensi (diberlakukan oleh pustaka runtime bahasa Anda). Itu semua hanya memori, dan mungkin tidak tersegmentasi kecuali Anda menjalankan dalam mode 8086 virtual. Setiap tumpukan thread adalah sepotong memori yang dialokasikan pada waktu pembuatan thread, dengan alamat top stack saat ini disimpan dalam register penunjuk tumpukan, dan setiap utas menyimpan penunjuk tumpukannya sendiri bersama dengan register lainnya.
[1] OK, saya tahu: masker sinyal, TSS / TSD dll. Ruang alamat, termasuk semua segmen program yang dipetakan, masih dibagikan.
sumber
Dalam kerangka kerja x86, seseorang dapat membagi banyak segmen (hingga 2 ^ 16-1). Arahan ASM SEGMENT / ENDS memungkinkan ini, dan operator SEG dan OFFSET memungkinkan inisialisasi register segmen. CS: IP biasanya diinisialisasi oleh loader, tetapi untuk DS, ES, SS aplikasi bertanggung jawab dengan inisialisasi. Banyak lingkungan memungkinkan apa yang disebut "definisi segmen yang disederhanakan" seperti .code, .data, .bss, .stack dll. Dan, tergantung juga pada "model memori" (kecil, besar, padat dll.) Loader memulai register segmen demikian. Biasanya .data, .bss, .stack, dan segmen biasa lainnya (saya belum melakukan ini sejak 20 tahun jadi saya tidak ingat semua) dikelompokkan dalam satu kelompok tunggal - itulah sebabnya biasanya DS, ES dan SS menunjuk ke area yang sama, tetapi ini hanya untuk menyederhanakan hal-hal.
Secara umum, semua register segmen dapat memiliki nilai yang berbeda saat dijalankan. Jadi, pertanyaan wawancara itu benar: yang mana dari KODE, DATA, dan STACK yang dibagikan di antara utas. Manajemen heap adalah sesuatu yang lain - itu hanya urutan panggilan ke OS. Tetapi bagaimana jika Anda tidak memiliki OS sama sekali, seperti dalam sistem tertanam - dapatkah Anda masih memiliki / menghapus baru dalam kode Anda?
Saran saya kepada orang-orang muda - baca beberapa buku pemrograman perakitan yang bagus. Tampaknya kurikulum universitas sangat buruk dalam hal ini.
sumber
Kutipan dari: Antarmuka Pemrograman Linux: Buku Pegangan Pemrograman Sistem Linux dan UNIX, Michael Kerrisk , halaman 619
sumber
Thread berbagi heap (ada penelitian tentang heap spesifik thread) tetapi implementasi saat ini berbagi heap. (dan tentu saja kodenya)
sumber
Dalam prosesnya, semua utas berbagi sumber daya sistem seperti memori tumpukan dll. Sementara utas memiliki tumpukan sendiri
Jadi ans Anda harus menumpuk memori yang berbagi semua utas untuk suatu proses.
sumber