Computer >> कंप्यूटर >  >> समस्या निवारण >> Android

अपने Android कर्नेल को नवीनतम Linux स्थिर में कैसे अपडेट करें

हमने एंड्रॉइड कर्नेल पर गाइड को कवर किया है, जैसे "कैसे एक कस्टम कर्नेल बनाएं" और "एंड्रॉइड के लिए सर्वश्रेष्ठ कस्टम कर्नेल", लेकिन आज हम आपको दिखाएंगे कि नवीनतम लिनक्स स्थिर के खिलाफ अपने कर्नेल को अपस्ट्रीम कैसे करें।

कृपया जान लें कि यह उन्नत . है सामान - यदि आपने पहले कभी कर्नेल संकलित नहीं किया है, तो आपको ऊपर लिंक "कस्टम कर्नेल कैसे बनाएं" गाइड का पालन करना चाहिए, और इस गाइड में आपके एंड्रॉइड कर्नेल के साथ नवीनतम लिनक्स-स्थिर कर्नेल से चेरी-पिकिंग और विलय शामिल होगा इससे पहले कि आप इसे संकलित करें।

अपने Android कर्नेल को नवीनतम Linux स्थिर में अपस्ट्रीम करने के बहुत सारे सकारात्मक लाभ हैं, जैसे नवीनतम सुरक्षा प्रतिबद्धताओं और बग फिक्स के साथ अप-टू-डेट रहना - हम इस गाइड में बाद में कुछ पेशेवरों और विपक्षों के बारे में बताएंगे।

लिनक्स-स्थिर कर्नेल क्या है?

अपने Android कर्नेल को नवीनतम Linux स्थिर में कैसे अपडेट करें

लिनक्स-स्थिर जैसा कि नाम से ही स्पष्ट है कि लिनक्स कर्नेल की स्थिर भुजा है। दूसरी भुजा को "मेनलाइन" के रूप में जाना जाता है, जो कि मास्टर शाखा . है . सभी Linux कर्नेल विकास मेनलाइन में होता है, और आम तौर पर इस प्रक्रिया का अनुसरण करता है:

  1. लिनस टॉर्वाल्ड दो सप्ताह के लिए अपने अनुरक्षकों से पैच का एक गुच्छा लेगा।
  2. इस दो सप्ताह के बाद, वह एक rc1 (उदा. 4.14-rc1) कर्नेल जारी करता है।
  3. अगले 6-8 सप्ताहों के लिए प्रत्येक सप्ताह के लिए, वह एक और RC (उदा. 4.14-rc2, 4.14-rc3, आदि) कर्नेल जारी करेगा, जिसमें केवल बग और प्रतिगमन समाधान शामिल हैं।
  4. एक बार जब इसे स्थिर माना जाता है, तो इसे org(उदा. 4.14) पर डाउनलोड करने के लिए टारबॉल के रूप में जारी किया जाएगा।

एलटीएस कर्नेल क्या हैं?

हर साल, ग्रेग एक कर्नेल उठाएगा और इसे दो साल (एलटीएस) या छह साल (विस्तारित एलटीएस) के लिए बनाए रखेगा। इन्हें ऐसे उत्पादों के लिए डिज़ाइन किया गया है जिन्हें स्थिरता की आवश्यकता होती है (जैसे Android फ़ोन या अन्य IOT डिवाइस)। प्रक्रिया ठीक ऊपर की तरह ही है, यह बस लंबे समय तक चलती है। वर्तमान में छह एलटीएस कर्नेल हैं (जिन्हें हमेशा kernel.org रिलीज़ पेज पर देखा जा सकता है) ):

  • 4.14 (LTS) , ग्रेग क्रोआह-हार्टमैन द्वारा अनुरक्षित
  • 4.9 (LTS) , ग्रेग क्रोआह-हार्टमैन द्वारा अनुरक्षित
  • 4.4 (ईएलटीएस) , ग्रेग क्रोआह-हार्टमैन द्वारा अनुरक्षित
  • 4.1(LTS) , साशा लेविन द्वारा अनुरक्षित
  • 3.16 (LTS) , बेन हचिंग्स द्वारा अनुरक्षित
  • 3.2 (LTS) , बेन हचिंग्स द्वारा अनुरक्षित

मेरे Android कर्नेल को Linux Stable पर अपस्ट्रीम करने के क्या लाभ हैं?

जब महत्वपूर्ण कमजोरियों का खुलासा/निश्चित किया जाता है, तो उन्हें प्राप्त करने वाले पहले स्थिर कर्नेल होते हैं। इस प्रकार, आपका Android कर्नेल हमलों, सुरक्षा खामियों और सामान्य रूप से केवल बगों के विरुद्ध अधिक सुरक्षित होगा।

लिनक्स स्थिर में बहुत से ड्राइवरों के लिए सुधार शामिल हैं जिनका उपयोग मेरा एंड्रॉइड डिवाइस नहीं करता है, क्या यह अधिकतर अनावश्यक नहीं है?

हां और नहीं, इस पर निर्भर करता है कि आप "ज्यादातर" को कैसे परिभाषित करते हैं। लिनक्स कर्नेल में बहुत सारे कोड शामिल हो सकते हैं जो एंड्रॉइड सिस्टम में अप्रयुक्त हो जाते हैं, लेकिन यह गारंटी नहीं देता है कि नए संस्करणों को मर्ज करते समय उन फाइलों से कोई विरोध नहीं होगा! समझें कि वस्तुतः कोई नहीं कर्नेल के हर एक हिस्से का निर्माण करता है, यहां तक ​​कि सबसे आम लिनक्स डिस्ट्रो जैसे उबंटू या मिंट भी नहीं। इसका मतलब यह नहीं है कि आपको ये सुधार नहीं करने चाहिए क्योंकि वहाँ हैं उन ड्राइवरों के लिए सुधार जो आप करते हैं Daud। उदाहरण के लिए arm/arm64 और ext4 लें, जो क्रमशः सबसे आम एंड्रॉइड आर्किटेक्चर और फाइल सिस्टम हैं। 4.4 में, 4.4.78 (नवीनतम Oreo CAF टैग का संस्करण) से 4.4.121 (नवीनतम अपस्ट्रीम टैग) तक, ये उन सिस्टम के कमिट के लिए निम्नलिखित नंबर हैं:

nathan@flashbox ~/kernels/linux-stable (master) $ git log --format=%h v4.4.78..v4.4.121 | wc -l2285 nathan@flashbox ~/kernels/linux-stable (master) $ git log --format=%h v4.4.78..v4.4.121 arch/arm | wc -l58 nathan@flashbox ~/kernels/linux-stable (master) $ git log --format=%h v4.4.78..v4.4.121 arch/arm64 | wc -l22 nathan@flashbox ~/kernels/linux-stable (master) $ git log --format=%h v4.4.78..v4.4.121 fs/ext4 | wc -l18

सबसे अधिक समय लेने वाला हिस्सा प्रारंभिक लाना है; एक बार जब आप सभी तरह से अद्यतित हो जाते हैं, तो एक नई रिलीज़ में विलय करने में बिल्कुल भी समय नहीं लगता है, जिसमें आमतौर पर 100 से अधिक कमिट नहीं होते हैं। हालांकि इससे जो लाभ मिलते हैं (आपके उपयोगकर्ताओं के लिए अधिक स्थिरता और बेहतर सुरक्षा) के लिए इस प्रक्रिया की आवश्यकता होनी चाहिए।

लिनक्स स्थिर कर्नेल को Android कर्नेल में कैसे मर्ज करें

सबसे पहले आपको यह पता लगाना होगा कि आपका Android डिवाइस कौन सा कर्नेल संस्करण चला रहा है।

यह जितना तुच्छ लगता है, यह जानना आवश्यक है कि आपको कहाँ से आरंभ करने की आवश्यकता है। अपने कर्नेल ट्री में निम्न कमांड चलाएँ:

make kernelversion

यह उस संस्करण को वापस कर देगा जिस पर आप हैं। पहले दो नंबरों का उपयोग आपके लिए आवश्यक शाखा का पता लगाने के लिए किया जाएगा (उदाहरण के लिए किसी भी 4.4 कर्नेल के लिए linux-4.4.y) और अंतिम संख्या का उपयोग यह निर्धारित करने के लिए किया जाएगा कि आपको विलय के साथ किस संस्करण को शुरू करने की आवश्यकता है (उदाहरण के लिए यदि आप 4.4 पर हैं) .21, आप आगे 4.4.22 मर्ज करेंगे)।

kernel.org से नवीनतम कर्नेल स्रोत प्राप्त करें

kernel.org नवीनतम कर्नेल स्रोत को linux-stable रिपॉजिटरी में रखता है। उस पेज के नीचे, तीन फ़ेच लिंक होंगे। मेरे अनुभव में, Google का दर्पण सबसे तेज़ होता है लेकिन आपके परिणाम भिन्न हो सकते हैं। निम्नलिखित कमांड चलाएँ:

git remote add linux-stable https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.gitgit fetch linux-stable

तय करें कि आप संपूर्ण कर्नेल को मर्ज करना चाहते हैं या चेरी-कमिट्स चुनें

इसके बाद, आपको यह चुनना होगा कि क्या आप कमिट या चेरी-पिक को मर्ज करना चाहते हैं। यहां प्रत्येक के पेशेवरों और विपक्षों के बारे में बताया गया है और जब आप उन्हें करना चाहते हैं।

नोट: यदि आपका कर्नेल स्रोत टैरबॉल के रूप में है, तो आपको संभवतः चेरी-पिक करने की आवश्यकता होगी, अन्यथा आपको हजारों फ़ाइल संघर्ष मिलेंगे क्योंकि गिट पूरी तरह से अपस्ट्रीम पर आधारित इतिहास को पॉप्युलेट कर रहा है, न कि ओईएम या सीएएफ ने क्या बदला है। बस चरण 4 पर जाएं।

चेरी चुनना:

पेशेवरों:

  • संघर्षों को हल करना आसान है क्योंकि आप जानते हैं कि वास्तव में कौन सा विरोध समस्या पैदा कर रहा है।
  • रीबेस करना आसान है क्योंकि प्रत्येक प्रतिबद्धता अपने आप होती है।
  • समस्याओं में आने पर द्विभाजित करना आसान

विपक्ष:

  • इसमें अधिक समय लगता है क्योंकि प्रत्येक प्रतिबद्धता को व्यक्तिगत रूप से चुनना होता है।
  • पहली नज़र में यह बताना थोड़ा मुश्किल है कि क्या प्रतिबद्धता अपस्ट्रीम से है

मर्ज करें

पेशेवरों :

  • यह तेज़ है क्योंकि आपको सभी साफ़ पैच के विलय के लिए प्रतीक्षा करने की आवश्यकता नहीं है।
  • यह देखना आसान है कि जब कोई कमिटमेंट अपस्ट्रीम से होता है तो आप कमिटर नहीं होंगे, अपस्ट्रीम मेंटेनर होंगे।

विपक्ष:

  • संघर्षों को हल करना थोड़ा अधिक कठिन हो सकता है क्योंकि आपको यह देखने की आवश्यकता होगी कि कौन सी प्रतिबद्धता git log/git दोष का उपयोग करके संघर्ष का कारण बन रही है, यह सीधे आपको नहीं बताएगा।
  • रीबेसिंग मुश्किल है क्योंकि आप मर्ज को रिबेस नहीं कर सकते हैं, यह व्यक्तिगत रूप से सभी कमिटमेंट को चेरी-पिक करने की पेशकश करेगा। हालांकि, आपको जहां संभव हो वहां गिट रिवर्ट और गिट मर्ज का उपयोग करने के बजाय, आपको अक्सर रिबेसिंग नहीं करनी चाहिए।

मैं शुरू में किसी भी समस्या का पता लगाने के लिए एक चेरी-पिक करने की सलाह दूंगा, एक मर्ज कर रहा हूं, फिर बाद में होने वाली समस्या को वापस कर दूंगा ताकि अपडेट करना आसान हो (क्योंकि विलय अप टू डेट होने के बाद तेज है)।

अपने स्रोत में कमिट्स जोड़ें, एक बार में एक संस्करण

इस प्रक्रिया का सबसे महत्वपूर्ण हिस्सा एक समय में एक संस्करण है। आपकी अपस्ट्रीम श्रृंखला में एक समस्या पैच हो सकता है, जो बूटिंग या ध्वनि या चार्जिंग जैसी किसी चीज़ के टूटने में समस्या पैदा कर सकता है (टिप्स और ट्रिक्स अनुभाग में समझाया गया है)। इस कारण से वृद्धिशील संस्करण परिवर्तन करना महत्वपूर्ण है, कुछ संस्करणों के लिए 2000 के ऊपर की तुलना में 50 कमिट्स में कोई समस्या ढूंढना आसान है। मैं केवल एक बार पूर्ण विलय करने की अनुशंसा करता हूं जब आप सभी समस्याओं के बारे में जानते हैं और विरोध समाधान करते हैं।

चेरी चुनना

प्रारूप:

git cherry-pick <previous_tag>..<next_tag>

उदाहरण:

गिट चेरी-पिक v3.10.73..v3.10.74

मर्ज करें

प्रारूप:

git merge <next_tag>

उदाहरण:

गिट मर्ज v3.10.74

मेरा सुझाव है कि # मार्करों को हटाकर मर्ज कमिट में विरोधों पर नज़र रखें।

संघर्षों का समाधान कैसे करें

हम हर एक संघर्ष को हल करने के लिए चरण-दर-चरण मार्गदर्शिका नहीं दे सकते, क्योंकि इसमें सी भाषा का अच्छा ज्ञान शामिल है, लेकिन यहां कुछ संकेत दिए गए हैं।

यदि आप विलय कर रहे हैं, तो पता लगाएं कि कौन सी प्रतिबद्धता संघर्ष का कारण बन रही है। आप इसे दो तरीकों में से एक कर सकते हैं:

  1. git log -p v$(makekernelversion).. अपस्ट्रीम से अपने वर्तमान संस्करण और नवीनतम के बीच परिवर्तन प्राप्त करने के लिए। -p ध्वज आपको प्रत्येक प्रतिबद्धता द्वारा किए गए परिवर्तनों को दिखाएगा ताकि आप देख सकें।
  2. क्षेत्र में प्रत्येक प्रतिबद्धता के हैश प्राप्त करने के लिए फ़ाइल पर git दोष चलाएँ। फिर आप यह देखने के लिए git show –format=fuller चला सकते हैं कि कमिटर मेनलाइन/स्थिर, Google, या CodeAurora से था या नहीं।
  • पता लगाएँ कि क्या आपके पास पहले से ही कमिटमेंट है। Google या CAF जैसे कुछ विक्रेता गंभीर बग के लिए अपस्ट्रीम देखने का प्रयास करेंगे, जैसे डर्टी काउ फिक्स, और उनके बैकपोर्ट अपस्ट्रीम के साथ संघर्ष कर सकते हैं। आप git log –grep="" चला सकते हैं और देख सकते हैं कि क्या यह कुछ लौटाता है। यदि ऐसा होता है, तो आप कमिटमेंट को छोड़ सकते हैं (यदि git रीसेट का उपयोग करके चेरी-पिकिंग -हार्ड &&git चेरी-पिक-जारी रखें) या विरोधों को अनदेखा करें (<<<<<< और सब कुछ को हटा दें ======और >>>>>>)।
  • पता लगाएँ कि कहीं कोई बैकपोर्ट तो नहीं है जो संकल्प को बिगाड़ रहा है। Google और CAF कुछ ऐसे पैच को बैकपोर्ट करना पसंद करते हैं जो स्थिर नहीं होंगे। Google को बैकपोर्ट करने का विकल्प चुनने वाले कुछ पैच की अनुपस्थिति के लिए स्थिर को अक्सर मेनलाइन प्रतिबद्धता के संकल्प को अनुकूलित करने की आवश्यकता होगी। आप git शो <हैश> चलाकर मेनलाइन कमिट को देख सकते हैं (मेनलाइन हैश स्टेबल कमिट के कमिट मैसेज में उपलब्ध होगा)। यदि कोई बैकपोर्ट इसे गड़बड़ कर रहा है, तो आप या तो परिवर्तनों को त्याग सकते हैं या आप मेनलाइन संस्करण का उपयोग कर सकते हैं (जो कि आपको आमतौर पर करने की आवश्यकता होगी)।
  • पढ़ें कि प्रतिबद्धता क्या करने की कोशिश कर रही है और देखें कि क्या समस्या पहले ही ठीक हो गई है। कभी-कभी सीएएफ अपस्ट्रीम से स्वतंत्र बग को ठीक कर सकता है, जिसका अर्थ है कि आप या तो अपस्ट्रीम के लिए उनके फिक्स को ओवरराइट कर सकते हैं या इसे ऊपर की तरह त्याग सकते हैं।

अन्यथा, यह केवल एक CAF/Google/OEM जोड़ का परिणाम हो सकता है, इस स्थिति में आपको बस कुछ चीज़ों में फेरबदल करने की आवश्यकता है।

यह रहा linux-stable kernel.org रिपॉजिटरी का मिरर गिटहब पर, जो प्रतिबद्ध सूचियों को देखने के लिए आसान हो सकता है और संघर्ष समाधान के लिए भिन्न हो सकता है। मैं अनुशंसा करता हूं कि पहले प्रतिबद्ध सूची दृश्य में जाएं और समस्या का पता लगाकर मूल अंतर को आपकी तुलना करने के लिए देखें।

उदाहरण यूआरएल: https://github.com/nathanchance/linux-stable/commits/linux-3.10.y/arch/arm64/mm/mmu.c

आप इसे कमांड लाइन के माध्यम से भी कर सकते हैं:

git log <current_version>..<version_being_added> <path>
git show <hash>

संकल्पों को हल करना संदर्भ के बारे में है। आपको हमेशा यह करना चाहिए कि दो अलग-अलग विंडो में निम्न कमांड चलाकर सुनिश्चित करें कि आपका अंतिम अंतर अपस्ट्रीम से मेल खाता है:

git diff HEAD
git diff v$(make kernelversion)..$(git tag --sort=-taggerdate -l v$(make kernelversion | cut -d . -f 1,2)* | head -n1)

रीरेरे सक्षम करें

Git में rerere (Reuse Recorded Resolution के लिए खड़ा है) नामक एक सुविधा है, जिसका अर्थ है कि जब यह एक संघर्ष का पता लगाता है, तो यह रिकॉर्ड करेगा कि आपने इसे कैसे हल किया ताकि आप इसे बाद में पुन:उपयोग कर सकें। यह विलय और चेरी-पिकिंग दोनों के साथ पुराने रिबेसर दोनों के लिए विशेष रूप से सहायक है क्योंकि आपको केवल git add चलाने की आवश्यकता होगी। &&git <मर्ज|चेरी-पिक> -अपस्ट्रीम को फिर से करते समय जारी रखें क्योंकि विरोध का समाधान हो जाएगा कि आपने इसे पहले कैसे हल किया था।

इसे आपके कर्नेल रेपो में निम्न कमांड चलाकर सक्रिय किया जा सकता है:

git config rerere.enabled true

संकलक या रनटाइम त्रुटि में चलते समय git bisect कैसे करें

यह देखते हुए कि आप बड़ी संख्या में कमिट जोड़ रहे हैं, आपके लिए एक कंपाइलर या रनटाइम त्रुटि पेश करना बहुत संभव है। बस हार मानने के बजाय, आप समस्या के मूल कारण का पता लगाने के लिए git के बिल्ट-इन बिसेक्ट टूल का उपयोग कर सकते हैं! आदर्श रूप से, जब आप इसे जोड़ते हैं तो आप हर एक कर्नेल संस्करण का निर्माण और चमकते रहेंगे, इसलिए यदि आवश्यक हो तो द्विभाजित करने में कम समय लगेगा लेकिन आप बिना किसी समस्या के 5000 कमिट को द्विभाजित कर सकते हैं।

git bisect क्या करेगा, यह कई प्रकार के कमिट लेता है, जहां से समस्या मौजूद है, जहां यह मौजूद नहीं था, और फिर कमिट रेंज को आधा करना शुरू करें, जिससे आप निर्माण और परीक्षण कर सकें और यह बता सकें कि यह अच्छा है या नहीं . यह तब तक जारी रहेगा जब तक कि यह आपकी समस्या का कारण बनने वाली प्रतिबद्धता को समाप्त नहीं कर देता। उस समय, आप या तो इसे ठीक कर सकते हैं या इसे पूर्ववत कर सकते हैं।

  1. द्विभाजित करना प्रारंभ करें: गिट द्विभाजित प्रारंभ
  2. वर्तमान संशोधन को खराब के रूप में लेबल करें:git bisect bad
  3. एक संशोधन को अच्छे के रूप में लेबल करें:git bisect good
  4. नए संशोधन के साथ निर्माण करें
  5. परिणाम के आधार पर (यदि समस्या मौजूद है या नहीं), तो git को बताएं: git bisect good या git bisect bad
  6. समस्या कमिट पाए जाने तक चरण 4-5 को धोएं और दोहराएं!
  7. समस्या को वापस लाएं या ठीक करें।

नोट: मर्ज को अस्थायी रूप से चलाने की आवश्यकता होगी git rebase -i उचित द्विभाजित करने के लिए आपकी शाखा में सभी पैच लागू करने के लिए, क्योंकि मर्ज के साथ द्विभाजित करने से अक्सर अपस्ट्रीम कमिट पर चेकआउट होता है, जिसका अर्थ है कि आपके पास Android विशिष्ट कमिट्स में से कोई भी नहीं है . मैं अनुरोध पर इस पर और गहराई में जा सकता हूं लेकिन मेरा विश्वास करो, इसकी आवश्यकता है। एक बार जब आप समस्या की पहचान कर लेते हैं, तो आप इसे वापस मर्ज कर सकते हैं या मर्ज में रीबेस कर सकते हैं।

अपस्ट्रीम अपडेट को स्क्वॉश न करें

बहुत सारे नए डेवलपर्स ऐसा करने के लिए ललचाते हैं क्योंकि यह "क्लीनर" और प्रबंधन के लिए "आसान" है। यह कुछ कारणों से भयानक है:

  • लेखन खो गया है। अन्य डेवलपर्स के लिए यह अनुचित है कि उनके काम के लिए उनका क्रेडिट छीन लिया जाए।
  • द्विभाजित करना असंभव है। यदि आप कमिट की एक श्रृंखला को तोड़ते हैं और उस श्रृंखला में कुछ समस्या है, तो यह बताना असंभव है कि स्क्वैश में किस प्रतिबद्धता के कारण समस्या हुई।
  • भविष्य में चेरी की पसंद कठिन है। यदि आपको एक कुचली हुई शृंखला के साथ पुन:आधार बनाने की आवश्यकता है, तो यह बताना कठिन/असंभव है कि संघर्ष कहाँ से उत्पन्न होता है।

समय पर अपडेट के लिए Linux कर्नेल मेलिंग सूची की सदस्यता लें

अपस्ट्रीम अपडेट होने पर सूचित करने के लिए, लिनक्स-कर्नेल-घोषणा सूची की सदस्यता लें . यह आपको हर बार एक नया कर्नेल जारी होने पर एक ईमेल प्राप्त करने की अनुमति देगा ताकि आप जितनी जल्दी हो सके अपडेट और पुश कर सकें।


  1. Android पर अपना आईपी पता कैसे छिपाएं

    आप वेब ब्राउज़ करने के लिए अपने Android डिवाइस का उपयोग करना पसंद कर सकते हैं क्योंकि यह अधिक सुविधाजनक है, और आप अपने पीसी या डेस्कटॉप का उपयोग करने की तुलना में आराम से वेब ब्राउज़ कर सकते हैं। हालाँकि, आप गोपनीयता की चिंताओं के लिए अपना आईपी पता छिपाना चाहते हैं या अपने ब्राउज़िंग अनुभव को बेहतर

  1. Android पर Snapchat अपडेट से कैसे छुटकारा पाएं

    स्नैपचैट आज सबसे लोकप्रिय सोशल मीडिया प्लेटफॉर्म में से एक है। अपने मनोरंजक फिल्टर के लिए प्रसिद्ध, यह शानदार ऐप आपको अपने दिन-प्रतिदिन के जीवन के क्षणों को अपने परिवार और दोस्तों के साथ साझा करने की अनुमति देता है। स्नैपचैट यूजर एक्सपीरियंस को बढ़ाने के लिए ऐप में सुधार करने के लिए अपडेट जारी करता

  1. कैसे जांचें कि आपका Android फोन रूट किया गया है या नहीं?

    अपने उपयोगकर्ता के अनुकूल, सीखने में आसान और आसानी से संचालित होने वाले OS संस्करणों के कारण Android के उपयोग में उपयोगकर्ताओं की संख्या में काफी वृद्धि देखी गई है। एक एंड्रॉइड स्मार्टफोन उपयोगकर्ताओं को शानदार सुविधाएं और विशिष्टताओं के साथ प्रदान करता है जो ग्राहकों को इसकी ओर आकर्षित करते हैं। इस