Kata pengantar
Dalam proses mempelajari mekanisme Binder di ServiceManager, ada masalah yang belum tercakup karena masalah ruang, dan begitulah cara MediaPlayerService terdaftar. Dengan memahami bagaimana MediaPlayerService terdaftar, Anda dapat mengetahui proses pendaftaran layanan sistem.
1. Jelaskan bagaimana MediaPlayerService terdaftar dari perspektif rantai panggilan
Pertama mari kita lihat fungsi entri MediaServer, kodenya ditunjukkan di bawah ini. frameworks / av / media / mediaserver / main_mediaserver.cpp
int main (int argc __unused, char ** argv __unused) { sinyal (SIGPIPE, SIG_IGN); // Dapatkan instance ProcessState sp < ProcessState > proc (ProcessState :: self ()); sp < IServiceManager > sm (defaultServiceManager ()); ALOGI ("ServiceManager:% p", sm.get ()); InitializeIcuOrDie (); // Daftarkan MediaPlayerService MediaPlayerService :: instantiate (); // 1 ResourceManagerService :: instantiate (); registerExtensions (); // Mulai kumpulan utas Binder ProcessState :: self () - > startThreadPool (); // Utas saat ini ditambahkan ke kumpulan utas IPCThreadState :: self () - > joinThreadPool (); }Banyak konten dalam kode ini diperkenalkan di artikel sebelumnya, dan kemudian menganalisis kode di komentar 1.
frameworks / av / media / libmediaplayerservice / MediaPlayerService.cpp
void MediaPlayerService :: instantiate () { defaultServiceManager () - > addService ( String16 ("media.player"), MediaPlayerService baru, ()); }Apa yang dikembalikan defaultServiceManager adalah BpServiceManager. Tidak jelas apakah Binder sangat lemah dan datang untuk mewawancarai Tencent? Artikel ini tentang mekanisme Binder di ServiceManager. Parameternya adalah string dan MediaPlayerService, yang terlihat seperti Key / Value untuk menyelesaikan pendaftaran, lalu lihat fungsi addService.
frameworks / native / libs / binder / IServiceManager.cpp
virtual status_t addService (nama const String16, const sp < IBinder > layanan, bool allowIsolated, int dumpsysPriority) { Data paket, balas; // paket data data.writeInterfaceToken (IServiceManager :: getInterfaceDescriptor ()); data.writeString16 (name); // nilai nama adalah "media.player" data.writeStrongBinder (service); // nilai layanan adalah MediaPlayerService data.writeInt32 (allowIsolated? 1: 0); data.writeInt32 (dumpsysPriority); status_t err = remote () - > transact (ADD_SERVICE_TRANSACTION, data, reply); // 1 return err == NO_ERROR? reply.readExceptionCode (): err; }Data adalah paket data, yang akan terus menulis data menjadi data nanti Remote () dalam Catatan 1 mengacu pada mRemote, yaitu BpBinder. Fungsi dari fungsi addService adalah untuk mengemas data yang diminta menjadi data, kemudian meneruskannya ke fungsi transact dari BpBinder dengan kode seperti di bawah ini.
frameworks / native / libs / binder / BpBinder.cpp
status_t BpBinder :: transact ( kode uint32_t, const Data parcel, Parcel * reply, uint32_t flags) { if (mAlive) { status_t status = IPCThreadState :: self () - > melakukan transaksi( mHandle, kode, data, balasan, bendera); jika (status == DEAD_OBJECT) mAlive = 0; status pengembalian; } kembali DEAD_OBJECT; }BpBinder menyerahkan pemrosesan logika ke IPCThreadState. Mari kita lihat apa yang dilakukan IPCThreadState :: self ()? frameworks / native / libs / binder / IPCThreadState.cpp
IPCThreadState * IPCThreadState :: self () { // Nilai gHaveTLS untuk pertama kali masuk adalah false if (gHaveTLS) { mengulang kembali: const pthread_key_t k = gTLS; // 1 IPCThreadState * st = (IPCThreadState *) pthread_getspecific (k); // 2 if (st) return st; mengembalikan IPCThreadState baru; // 3 } ... pthread_mutex_unlock (gTLSMutex); goto restart; }Catatan 1 Nama lengkap TLS adalah penyimpanan lokal Thread, yang mengacu pada ruang penyimpanan lokal thread Ada TLS di setiap thread dan tidak dibagikan antar-thread. Catatan 2 digunakan untuk mendapatkan konten di TLS dan menetapkannya ke penunjuk IPCThreadState *. Catatan 3 akan membuat IPCThreadState baru, di sini Anda dapat mengetahui bahwa IPCThreadState :: self () sebenarnya untuk membuat IPCThreadState, konstruktornya adalah sebagai berikut.
frameworks / native / libs / binder / IPCThreadState.cpp
IPCThreadState :: IPCThreadState () : mProcess (ProcessState :: self ()), mStrictModePolicy (0), mLastTransactionBinderFlags (0) { pthread_setspecific (gTLS, this); // 1 clearCaller (); mIn.setDataCapacity (256); mOut.setDataCapacity (256); }Fungsi pthread_setspecific di Catatan 1 digunakan untuk menyetel TLS, meneruskan TLS yang diperoleh oleh IPCThreadState :: self () dan dirinya sendiri.
IPCThreadState juga berisi mIn dan mOut, di mana mIn digunakan untuk menerima data dari driver Binder, dan mOut digunakan untuk menyimpan data yang dikirim ke driver Binder. Ukuran defaultnya adalah 256 byte.
Ketahui konstruktor IPCThreadState, kembali untuk melihat fungsi transact dari IPCThreadState.
frameworks / native / libs / binder / IPCThreadState.cpp
status_t IPCThreadState :: transact (pegangan int32_t, kode uint32_t, const Data Parcel, Parcel * reply, uint32_t flags) { status_t err; bendera | = TF_ACCEPT_FDS; ... err = writeTransactionData (BC_TRANSACTION, flags, handle, code, data, NULL); // 1 jika (err! = NO_ERROR) { if (reply) reply- > setError (err); kembali (mLastError = err); } if ((flags dan TF_ONE_WAY) == 0) { ... if (reply) { err = waitForResponse (reply); // 2 } lain { Parcel fakeReply; err = waitForResponse (fakeReply); } ... } lain { // Tidak perlu menunggu cabang balasan err = waitForResponse (NULL, NULL); } kembali salah; }Memanggil fungsi transact dari BpBinder sebenarnya memanggil fungsi transact dari IPCThreadState. Fungsi writeTransactionData di Catatan 1 digunakan untuk mentransfer data. Parameter pertama BC_TRANSACTION mewakili protokol perintah yang dikirim ke driver Binder. Protokol perintah yang dikirim ke perangkat Binder dimulai dengan BC_, dan protokol perintah yang dikembalikan oleh driver Binder dimulai dengan BR_. Mari kita ingat perjanjian perintah ini, dan kita akan merujuknya lagi nanti.
Sekarang mari kita analisis fungsi writeTransactionData catatan 1 dan fungsi waitForResponse catatan 2.
1.1 Analisis fungsi writeTransactionData
frameworks / native / libs / binder / IPCThreadState.cpp
status_t IPCThreadState :: writeTransactionData (int32_t cmd, uint32_t binderFlags, pegangan int32_t, kode uint32_t, data paket const, status_t * statusBuffer) { binder_transaction_data tr; // 1 tr.target.ptr = 0; tr.target.handle = handle; // 2 tr.code = code; // code = ADD_SERVICE_TRANSACTION tr.flags = binderFlags; tr.cookie = 0; tr.sender_pid = 0; tr.sender_euid = 0; const status_t err = data.errorCheck (); // 3 jika (err == NO_ERROR) { tr.data_size = data.ipcDataSize (); tr.data.ptr.buffer = data.ipcData (); tr.offsets_size = data.ipcObjectsCount () * sizeof (binder_size_t); tr.data.ptr.offsets = data.ipcObjects (); } lain jika (statusBuffer) { tr.flags | = TF_STATUS_CODE; * statusBuffer = err; tr.data_size = sizeof (status_t); tr.data.ptr.buffer = reinterpret_cast < uintptr_t > (statusBuffer); tr.offsets_size = 0; tr.data.ptr.offsets = 0; } lain { kembali (mLastError = err); } mOut.writeInt32 (cmd); // cmd = BC_TRANSACTION mOut.write (tr, sizeof (tr)); kembali NO_ERROR; }Struktur binder_transaction_data (struktur tr) di Catatan 1 adalah struktur data yang mendorong komunikasi ke Binder. Dalam Catatan 2, pegangan diteruskan ke pegangan target untuk mengidentifikasi target. Nilai pegangan di sini adalah 0, yang mewakili ServiceManager. Catatan 3 melakukan pengecekan kesalahan pada data data, jika tidak ada kesalahan, tetapkan data ke struktur tr yang sesuai. Akhirnya, struktur BC_TRANSACTION dan tr akan dituliskan ke dalam mOut.
Diagram urutan dari rantai panggilan kode di atas ditunjukkan di bawah ini.
1.2 analisis fungsi waitForResponse
Kemudian lihat kembali untuk melihat apa fungsi fungsi waitForResponse Ada banyak pernyataan kasus dalam fungsi waitForResponse, jadi ini adalah bagian dari kodenya. frameworks / native / libs / binder / IPCThreadState.cpp
status_t IPCThreadState :: waitForResponse (Balasan paket *, status_t * memperolehResult) { uint32_t cmd; int32_t err; sementara (1) { if ((err = talkWithDriver ()) < NO_ERROR) putus; // 1 err = mIn.errorCheck (); jika (err < NO_ERROR) istirahat; if (mIn.dataAvail () == 0) lanjutkan; cmd = (uint32_t) mIn.readInt32 (); IF_LOG_COMMANDS () { alog < < "Memproses Perintah waitForResponse:" < < getReturnString (cmd) < < endl; } saklar (cmd) { case BR_TRANSACTION_COMPLETE: jika (! reply! memperolehResult) goto selesai; istirahat; kasus BR_DEAD_REPLY: err = DEAD_OBJECT; pergi selesai; ... default: // Memproses berbagai protokol perintah err = mengeksekusiCommand (cmd); if (err! = NO_ERROR) goto finish; istirahat; } } selesai: ... kembali salah; }Catatan 1 Fungsi talkWithDriver berkomunikasi dengan driver Binder melalui ioctl. Kode ditampilkan di bawah ini. frameworks / native / libs / binder / IPCThreadState.cpp
status_t IPCThreadState :: talkWithDriver (bool doReceive) { jika (mProcess- > mDriverFD < = 0) { kembali -EBADF; } // Struktur untuk komunikasi dengan driver Binder binder_write_read bwr; // 1 // Apakah mIn memiliki data yang dapat dibaca? Data yang diterima disimpan dalam mIn const bool needRead = mIn.dataPosition () > = mIn.dataSize (); const size_t outAvail = (! doReceive || needRead)? mOut.dataSize (): 0; bwr.write_size = outAvail; bwr.write_buffer = (uintptr_t) mOut.data (); // 2 // Nilai doReceive saat ini benar if (doReceive needRead) { bwr.read_size = mIn.dataCapacity (); bwr.read_buffer = (uintptr_t) mIn.data (); // 3 } lain { bwr.read_size = 0; bwr.read_buffer = 0; } ... if ((bwr.write_size == 0) (bwr.read_size == 0)) return NO_ERROR; bwr.write_consumed = 0; bwr.read_consumed = 0; status_t err; lakukan { IF_LOG_COMMANDS () { alog < < "Tentang membaca / menulis, tulis ukuran =" < < mOut.dataSize () < < endl; } #if ditentukan (__ ANDROID__) jika (ioctl (mProcess- > mDriverFD, BINDER_WRITE_READ, bwr) > = 0) // 4 err = NO_ERROR; lain err = -errno; #lain err = INVALID_OPERATION; #berakhir jika ... } sementara (err == -EINTR); ... kembali salah; }Binder_write_read pada catatan 1 adalah struktur yang berkomunikasi dengan driver Binder. Dalam catatan 2 dan 3, tetapkan mOut dan mIn ke bidang yang sesuai dari binder_write_read, dan terakhir berkomunikasi dengan driver Binder melalui fungsi ioctl pada catatan 4. Bagian ini melibatkan Driver Konten Binder tidak akan diperkenalkan secara detail.
1.3 Bagian
Dari perspektif rantai panggilan, bagaimana MediaPlayerService terdaftar tampaknya tidak rumit, karena berikut ini hanya pengantar singkat untuk cabang rantai panggilan, yang dapat diringkas secara singkat sebagai langkah-langkah berikut:
2. Jelaskan bagaimana MediaPlayerService terdaftar dari perspektif proses
Sebenarnya, pendaftaran MediaPlayerService juga melibatkan proses, seperti yang ditunjukkan pada gambar di bawah ini.
Dapat dilihat dari gambar yang didasarkan pada arsitektur C / S, dan addService dilakukan di MediaPlayerService, yang merupakan sisi Client dan digunakan untuk meminta penambahan layanan sistem. Sisi Server mengacu pada ServiceManager, yang digunakan untuk menyelesaikan penambahan layanan sistem.
Sisi Klien dan sisi Server masing-masing berjalan dalam dua proses, dan berkomunikasi melalui Binder. Penjelasan yang lebih rinci adalah bahwa kedua ujung melengkapi penambahan layanan sistem dengan mengirimkan protokol perintah ke driver Binder. Ada banyak protokol perintah, dan prosesnya lebih rumit. Protokol perintah disederhanakan di sini, dan hanya empat protokol perintah yang terlibat. Proses BC_TRANSACTION dan BR_TRANSACTION adalah transaksi lengkap, dan BC_REPLY serta BR_REPLY adalah transaksi lengkap.
Protokol perintah yang dikirim oleh Klien dan Server ke pengandar Pengikat dimulai dengan BC, dan protokol perintah yang dikembalikan oleh pengandar Binder ke Klien dan Server dimulai dengan BR_.
Langkah-langkahnya adalah sebagai berikut:
1. Klien mengirimkan perintah BC_TRANSACTION ke driver Binder. 2. Pengandar Binder menghasilkan perintah BR_TRANSACTION setelah menerima permintaan, dan mengirim perintah BR_TRANSACTION ke ServiceManager setelah membangunkan sisi Server. 3. Setelah pendaftaran layanan di sisi Server selesai, perintah BC_REPLY dibuat dan dikirim ke driver Binder. 4. Pengandar Binder menghasilkan perintah BR_REPLY, dan mengirimkan perintah BR_REPLY ke klien setelah membangunkan klien.
Perintah protokol ini digunakan untuk menjalankan dan menyelesaikan pendaftaran layanan sistem.
3. Ringkasan
Artikel ini menjelaskan bagaimana MediaPlayerService terdaftar dari perspektif rantai panggilan dan perspektif proses, dan secara tidak langsung mendapatkan bagaimana layanan terdaftar. Kedua perspektif ini lebih rumit, jadi berikut adalah penyederhanaan dari kedua perspektif tersebut masing-masing.Sebagai pengembangan aplikasi, kita tidak perlu terlalu banyak memperhatikan proses dan detailnya, hanya perlu memahami langkah-langkah umumnya.
Terakhir, ada beberapa hal yang tidak hanya harus Anda pahami, tetapi juga harus dapat Anda ungkapkan dengan baik agar pewawancara dapat mengenali pemahaman Anda, seperti mekanisme Handler yang merupakan pertanyaan wajib dalam wawancara. Ada beberapa poin yang tidak jelas, mungkin hanya tinggal dalam wawancara, Anda tidak akan menggunakannya sama sekali dalam pekerjaan yang sebenarnya, tetapi Anda harus tahu apa itu.
Ini akan menjadi musim puncak untuk wawancara tentang emas, perak dan perak. Semua orang berharap menggunakan kesempatan ini untuk menemukan pekerjaan favorit. Namun bagaimanapun wawancaranya apapun itu, jika ingin menghindari pelecehan oleh pewawancara, anda harus memaksimalkan pertanyaan wawancara dan membuat persiapan yang komprehensif.Tentunya selain itu, anda juga perlu meletakkan dasar yang kokoh di masa damai. , Jadi tidak peduli bagaimana pewawancara menggali poin pengetahuannya sendiri, Anda juga bisa mengatasinya ~
Wawancara: Jika Anda tidak mempersiapkan wawancara yang memadai, itu akan membuang-buang waktu dan Anda tidak akan bertanggung jawab untuk diri sendiri!
Musim Wawancara Golden Three Silver Four, buruan dan persiapkan wawancaramu!
Terakhir, editor di sini membagikan koleksi lusinan set yang terkait dengan diagram sistem teknis di atas. Pertanyaan wawancara dari Tencent, Toutiao, Ali, Meituan dan perusahaan lain selama 19 tahun , Mengatur poin-poin teknis ke dalam video dan PDF (sebenarnya butuh lebih banyak energi dari yang diharapkan), termasuk Konteks pengetahuan + banyak detail , Karena keterbatasan tempat, berikut ini sebagian berupa gambar.
dan juga Teknologi arsitektur canggih peta pikiran canggih, materi khusus wawancara pengembangan Android , Materi kerangka lanjutan tingkat lanjut untuk membantu semua orang belajar meningkatkan tingkat mahir, dan juga menghemat waktu setiap orang untuk mencari materi di Internet untuk dipelajari, dan mereka juga dapat dibagikan dengan teman-teman di sekitar untuk belajar bersama.
[Catatan tentang pengetahuan inti pengembangan Android]
[Peta pikiran Android (pohon keterampilan)]
[Dokumen PDF teknologi canggih inti Android, analisis pertanyaan nyata dalam wawancara BAT]
[Sumber Daya Pembelajaran Video Arsitektur Lanjutan Android]
Setelah menerima dan mempelajari Video Pengenalan Android, itu bahkan lebih hebat! Masuk pabrik BATJ dan sebagainya (persiapan)! Saat ini, dikatakan bahwa Internet itu dingin. Faktanya, itu tidak lebih dari Anda masuk ke mobil yang salah dan Anda memakai lebih sedikit (keterampilan). Jika Anda masuk ke mobil yang tepat dan kemampuan teknis Anda cukup kuat, biaya penggantian perusahaan tinggi. Bagaimana Anda bisa diberhentikan? Ini hanya untuk menghilangkan bisnis akhir Curd! Saat ini, ada banyak sekali programmer junior di pasar. Kumpulan tutorial ini ditujukan untuk teknisi pengembangan Android yang berusia 1-6 tahun. Mereka berada dalam periode hambatan. Mereka yang ingin menembus kenaikan gaji mereka di tahun depan, Android lanjutan menengah dan senior, arsitek bahkan lebih penting bagi Anda. Seperti ikan di air, dapatkan dengan cepat!
[Video pembelajaran lanjutan Android], [set lengkap wawancara Android menipu PDF], [Catatan pengetahuan inti pengembangan Android] dapat diperoleh melalui pesan pribadi [Android] gratis!
- Seluler: Epidemi melanda separuh langit, dan pemrogram harus berjuang untuk mendapatkan kekuatan jika mereka menginginkan stabilitas
- Pernahkah Anda berpikir untuk berganti pekerjaan? Di sini, arsitek Android memiliki beberapa saran dan persiapan untuk wawancara
- Apakah Anda siap untuk mendapatkan emas tiga perak empat: berikut adalah pertanyaan wawancara wajib-pertanyaan Android 20 dan analisis terperinci
- Bagaimana mempersiapkan pertanyaan wawancara bagi pemrogram seluler untuk berganti pekerjaan dan meningkatkan tingkat keberhasilan wawancara hingga 80%?