আমাদের এক্সিকিউটিভ ফাংশনে দুবার ফাইলের নাম কেন পাস করতে হবে?


12

স্টিভেনস, অষ্টম অধ্যায় দ্বারা আমি ইউনিক্স পরিবেশে উন্নত প্রোগ্রামিং পড়ি । আমি এক্সিকিউট ফাংশনগুলির ছয়টি পড়ি এবং বুঝতে পারি।

একটি জিনিস আমি লক্ষ্য করি, সমস্ত নির্বাহী কার্যক্রমে:

  • প্রথম যুক্তি হ'ল ফাইলের নাম / পথের নাম (এক্সিকিউট ফাংশনের উপর নির্ভর করে)।
  • দ্বিতীয় যুক্তিটি হল argv [0] যা আমরা পেয়ে যাই main()যা ফাইলটির নিজের নাম।

সুতরাং এখানে আমরা ফাংশন মধ্যে ফাইলের নাম দুইবার পাস করতে হবে।

এর কোনও কারণ আছে (যেমন আমরা প্রথম যুক্তি থেকে পথের নাম থেকে ফাইলের নামটি পেতে পারি না)?

উত্তর:


15

সুতরাং এখানে আমরা ফাংশন মধ্যে ফাইলের নাম দুইবার পাস করতে হবে।

তারা পুরোপুরি একই জিনিস হিসাবে আপনি যে নিরীক্ষক দ্বারা লক্ষ্য করা হয় এক তাদের হিসাবে ব্যবহার করা হয় argv[0]মান। এটি এক্সিকিউটেবলের বেসনামের মতো হতে হবে না; অনেকগুলি / বেশিরভাগ জিনিস এটিকে উপেক্ষা করে এবং আপনি যা চান সেখানে রাখতে পারেন।

প্রথমটি হ'ল কার্যনির্বাহী হওয়ার আসল পথ, যার জন্য একটি সুস্পষ্ট প্রয়োজনীয়তা রয়েছে। দ্বিতীয়টি প্রসেস হিসাবে প্রেরণ করা হয় নাম হিসাবে এটি প্রার্থনা করার জন্য ব্যবহৃত হয়, তবে, উদাহরণস্বরূপ:

execl("/bin/ls", "banana", "-l", NULL);

ঠিকঠাক কাজ করবে, অনুমান /bin/lsকরা সঠিক পথ।

কিছু অ্যাপ্লিকেশন অবশ্য ব্যবহার করে argv[0]। সাধারণত এগুলির মধ্যে এক বা একাধিক প্রতীক থাকে $PATH; এটি সংক্ষেপণ ইউটিলিটিগুলির সাথে সাধারণ (কখনও কখনও তারা পরিবর্তে শেল র‌্যাপার ব্যবহার করে)। আপনি যদি xzইনস্টল করে থাকেন তবে stat $(which xzcat)এটির একটি লিঙ্ক দেখায় xzএবং man xzcatএটি man xz"xzcat xz --decompress --stdout এর সমতুল্য" বলে ব্যাখ্যা করে explains এক্সজেডের উপায়টি কীভাবে এটি আহ্বান জানানো হয়েছিল তা পরীক্ষা argv[0]করে এই সমতুল্য করে তৈরি করা যায়:

execl("/bin/xz", "xzcat", "somefile.xz", NULL);
execl("/bin/xz", "xz", "--decompress", "--stdout", "somefile.xz", NULL);

5
আহ, সুতরাং এটি ব্যাখ্যা করবে busyboxযে আপনি কীভাবে এটি সঠিকভাবে কল করতে পারেন তার উপর নির্ভর করে আপনি এটি চান কী হতে পারে?
টেরডন

4
@terdon ঠিক ঠিক কীভাবে ব্যস্তবক্সের জন্য একক বাইনারি বিভিন্ন বিভিন্ন কমান্ডকে সন্তুষ্ট করে।
মাহ

7
যার অর্থ /bin/lsহ'ল ব্যস্তবক্স থাকলে কীভাবে চালানো যায় তা জানত না banana!
রিকিং

6

আপনাকে দুবার ফাইলের নাম পাস করতে হবে না।

প্রথমটি হ'ল ফাইলটি যা আসলে সম্পাদিত হয়।

দ্বিতীয় যুক্তি হ'ল argv[0]প্রক্রিয়াটির কী হওয়া উচিত , অর্থাৎ প্রক্রিয়াটির নাম হিসাবে কী দেখা উচিত। যেমন আপনি যদি lsশেল থেকে চালান , প্রথম যুক্তিটি হ'ল /bin/ls, দ্বিতীয়টি ঠিক ls

আপনি একটি নির্দিষ্ট ফাইল সম্পাদন করতে পারেন এবং দ্বিতীয় আর্গুমেন্টের মাধ্যমে একে অন্য কিছু কল করতে পারেন; প্রোগ্রামটি তার নামটি পরীক্ষা করতে পারে এবং নাম অনুসারে আলাদা আচরণ করতে পারে। এটি হার্ড লিঙ্কগুলির (বা প্রতীকী লিঙ্কগুলি) এর মাধ্যমেও করা যেতে পারে তবে এই উপায়টি আরও নমনীয়তা দেয়।


আসলে লিঙ্কগুলি একই পদ্ধতি হ'ল যেহেতু argv[0]লিঙ্কটির নামের সাথে সেট করে।
সোনারলোকস

শেষ অনুচ্ছেদে, "আপনি একটি নির্দিষ্ট ফাইল সম্পাদন করতে পারেন এবং দ্বিতীয় আর্গুমেন্টের মাধ্যমে একে অন্যকে কল করতে পারেন; প্রোগ্রামটি তার নামটি পরীক্ষা করতে পারে এবং নাম অনুসারে 'আলাদাভাবে' আচরণ করতে পারে"। আপনি কি দয়া করে বিস্তারিত বলতে পারেন বা আমাকে কিছু রিডিং দিতে পারেন, আমি এই পরিবেশে একটি নতুন।
munjal007

গোল্ডিলোকসের উত্তরের শেষ অংশটি এটি ব্যাখ্যা করে।

1

গ্রহণটি হ'ল এটি যে argv[0]কোনও কিছুতে সেট করা যেতে পারে (সহ NULL)। কনভেনশন অনুসারে , argv[0]এক্সিকিউটেবল যে পথে শুরু হয়েছিল তা নির্ধারণ করা হবে (শেল প্রক্রিয়া দ্বারা যখন এটি হয় execve())।

যদি ./fooএবং dir/barএকই এক্সিকিউটেবল করার দুটি ভিন্ন সংযোগগুলি (হার্ড বা সিম্বলিক) হয়, তারপর দুই পাথ ব্যবহার সেট হবে শেল থেকে প্রোগ্রাম আরম্ভ করার argv[0]জন্য ./fooএবং dir/barযথাক্রমে।

যে বিষয়টি argv[0]হতে পারে NULLতা প্রায়শই উপেক্ষা করা হয়। নিম্নলিখিত কোডটি NULL argv[0]উদাহরণস্বরূপ ক্র্যাশ হতে পারে (যদিও গ্লিবসি এর পরিবর্তে <নুল> এর মতো কিছু প্রিন্ট করে argv[0]):

if (argc != 3) {
    fprintf(stderr, "%s: expected 2 arguments\n", argv[0]);
    exit(EXIT_FAILURE);
}

এই /proc/self/exeজাতীয় ক্ষেত্রে লিনাক্সের বিকল্প ব্যবহার করা।


আপনি কীভাবে আরগভি [0] সেট করতে পারেন ./foo এবং দির / বার
মুঞ্জাল007

@ munjal007 আমি অস্পষ্ট হয়ে থাকলে দুঃখিত। আমি প্রোগ্রামটি দু'বার চালাতে চাইছিলাম: একবার ./fooএবং একবার হিসাবে dir/barargv[0]এই দুটি ক্ষেত্রে পৃথক হবে (প্রতিটি ক্ষেত্রে এটি আপনি যেভাবে ব্যবহার করেছেন সেই পথের মতো হবে)।
16:39

@ মুঞ্জাল007 এটি ধরে নিচ্ছে যে আপনি অবশ্যই এটি শেল থেকে চালাচ্ছেন। মুল বক্তব্যটি হ'ল আপনি নিজে argv[0]যখন exec*()প্রোগ্রাম করেন তখন আপনি যে কোনও কিছুতে সেট করতে পারেন । argv[0]প্রোগ্রামটি শুরু করার জন্য যে পথটি ব্যবহৃত হয়েছিল সেটি সেট করার জন্য এটি শেলের একটি সম্মেলন (এবং আপনি যখন exec*()কোনও প্রোগ্রাম করেন তখন একই কাজ করা বুদ্ধিমান , যেহেতু অনেক প্রোগ্রাম পরিদর্শন করে argv[0]এবং পথটি ধরে রাখার প্রত্যাশা করে)।
Ulfalizer
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.