সিগন্যাল ধরা পড়লে সিস্টেম কলগুলির বাধা


29

ম্যান পৃষ্ঠাগুলি read()এবং write()কলগুলিতে পড়া থেকে দেখা যাচ্ছে যে এই কলগুলি ব্লক করতে হবে কিনা তা নির্বিশেষে সংকেত দ্বারা বাধাগ্রস্থ হয়।

বিশেষত, ধরে নিই

  • একটি প্রক্রিয়া কিছু সংকেতের জন্য একটি হ্যান্ডলার স্থাপন করে।
  • একটি ডিভাইস দিয়ে খোলা হয় (বলুন, একটি টার্মিনাল) O_NONBLOCK না সেট (অর্থাত মোড ব্লকিংয়ের অপারেটিং)
  • প্রক্রিয়াটি তখন read()ডিভাইস থেকে পড়তে সিস্টেম কল করে এবং ফলস্বরূপ কার্নেল-স্পেসে কার্নেল নিয়ন্ত্রণের পথটি কার্যকর করে।
  • প্র্যাক্সেসটি read()কার্নেল-স্পেসে এটি সম্পাদন করার সময় , হ্যান্ডলারটি আগে ইনস্টল করা হয়েছিল এমন সিগন্যালটি সেই প্রক্রিয়াতে সরবরাহ করা হয় এবং এর সংকেত হ্যান্ডলারটি অনুরোধ করা হয়।

ম্যান পেজগুলি এবং SUSv3 'সিস্টেম ইন্টারফেস ভলিউম (এক্সএসএইচ)' এর উপযুক্ত বিভাগগুলি পড়লে দেখা যায় যে:

আমি। read()কোনও তথ্য পড়ার আগে যদি কোনও সিগন্যালে বাধা সৃষ্টি করে (যেমন এটি কোনও ডেটা উপলভ্য ছিল না কারণ এটি ব্লক করতে হয়েছিল), এটি errno[EINTR] এ সেট করে -1 প্রদান করে ।

আ। read()কোনও ডেটা সফলভাবে কিছু ডেটা পড়ার পরে যদি কোনও সিগন্যালের দ্বারা বাধা হয়ে থাকে (যেমন অনুরোধটি তাত্ক্ষণিকভাবে পরিবেশন করা সম্ভব হয়েছিল), এটি পঠিত বাইটের সংখ্যা প্রদান করে।

প্রশ্ন এ): আমি কি ধরে নিচ্ছি যে উভয় ক্ষেত্রেই (ব্লক / নো ব্লক) সিগন্যাল সরবরাহ ও পরিচালনা পুরোপুরি স্বচ্ছ নয় read()?

মামলা i। বোধগম্যতা বোঝার মতো বলে মনে হচ্ছে যেহেতু এই ব্লকিংটি read()সাধারণত প্রক্রিয়াটিকে TASK_INTERRUPTIBLEরাজ্যে রাখে যাতে যখন কোনও সংকেত সরবরাহ করা হয় তখন কার্নেলটি প্রক্রিয়াটিকে TASK_RUNNINGরাজ্যে রাখে।

তবে যখন যখন read()ব্লক করার প্রয়োজন নেই (কেস ii।) এবং কার্নেল-স্পেসে অনুরোধটি প্রক্রিয়া করা হচ্ছে, তখন আমি ভেবেছিলাম যে সিগন্যালের আগমন এবং এর পরিচালনা হ'ল এইচডাব্লুয়ের আগমন এবং সঠিক পরিচালনার মতো স্বচ্ছ হবে would বাধা হবে। বিশেষত আমি ধরে নিয়েছি যে সংকেত সরবরাহের পরে, প্রক্রিয়াটি অস্থায়ীভাবে ব্যবহারকারীর মোডে স্থাপন করা হবে তার সিগন্যাল হ্যান্ডলারটি চালিত করার জন্য যা থেকে এটি অবশেষে ফিরে আসবে বিঘ্নিত read()(কার্নেল-স্পেসে) প্রসেসিং শেষ করার জন্য যাতে read()রানগুলি তার রান করে কোর্সটি সম্পূর্ণ হওয়ার পরে যার read()ফলস্বরূপ উপলব্ধ সমস্ত বাইটগুলি সহ কলটি করার পরে প্রক্রিয়াটি ফিরে আসে (ব্যবহারকারী-স্পেসে) after

তবে ii। read()এটিকে বোঝা যাচ্ছে যে বাধা পেয়েছে, যেহেতু ডেটা অবিলম্বে উপলব্ধ, তবে এটি কেবলমাত্র কিছু তথ্য (সমস্ত পরিবর্তে) প্রদান করে।

এটি আমার দ্বিতীয় (এবং চূড়ান্ত) প্রশ্নের কাছে নিয়ে আসে:

প্রশ্ন খ): ক এর অধীনে আমার ধারণাটি যদি সঠিক read()হয় তবে অনুরোধটি পূরণের জন্য তাত্ক্ষণিকভাবে ডেটা উপস্থিত থাকার কারণে এটি ব্লক করার প্রয়োজন নেই কেন, তা কেন বাধা পাবে? অন্য কথায়, read()সিগন্যাল হ্যান্ডলারটি কার্যকর করার পরে পুনরায় চালু করা হয় না কেন , ফলস্বরূপ উপলব্ধ সমস্ত ডেটা (যা সর্বোপরি উপলব্ধ ছিল) ফিরে আসে?

উত্তর:


29

সংক্ষিপ্তসার: আপনি সঠিক যে সংকেত প্রাপ্তি স্বচ্ছ নয়, i (কোনও কিছু না পড়ে বাধা দেওয়া) বা ii (আংশিক পড়ার পরে বাধাগ্রস্ত) ক্ষেত্রেও নয়। অন্যথায় যদি করণীয় হয় তবে অপারেটিং সিস্টেমের আর্কিটেকচার এবং অ্যাপ্লিকেশনগুলির আর্কিটেকচারে উভয় ক্ষেত্রেই মৌলিক পরিবর্তন প্রয়োজন making

ওএস বাস্তবায়ন দর্শন

যদি কোনও সিস্টেম কল একটি সিগন্যাল দ্বারা বাধাগ্রস্ত হয় তবে কী হবে তা বিবেচনা করুন। সিগন্যাল হ্যান্ডলার ব্যবহারকারী-মোড কোড সম্পাদন করবে। তবে সিস্কেল হ্যান্ডলারটি কার্নেল কোড এবং কোনও ব্যবহারকারী-মোড কোডকে বিশ্বাস করে না। সুতরাং আসুন সিস্কল হ্যান্ডলারের জন্য পছন্দগুলি অনুসন্ধান করুন:

  • সিস্টেম কলটি সমাপ্ত; ব্যবহারকারী কোডে কতটা করা হয়েছিল তা রিপোর্ট করুন। এটি যদি প্রয়োজন হয় তবে কোনওভাবে সিস্টেম কল পুনরায় চালু করতে অ্যাপ্লিকেশন কোডের উপর নির্ভর করে। ইউনিক্স এইভাবে কাজ করে।
  • সিস্টেম কলের অবস্থা সংরক্ষণ করুন এবং ব্যবহারকারী কোডটিকে কলটি আবার শুরু করার অনুমতি দিন। এটি বেশ কয়েকটি কারণে সমস্যাযুক্ত:
    • ব্যবহারকারীর কোড চলাকালীন, সংরক্ষিত অবস্থা অবৈধ করার জন্য কিছু ঘটতে পারে। উদাহরণস্বরূপ, যদি কোনও ফাইল থেকে পড়া হয় তবে ফাইলটি কেটে যেতে পারে। সুতরাং কার্নেল কোডে এই কেসগুলি পরিচালনা করতে প্রচুর যুক্তি প্রয়োজন।
    • সংরক্ষিত রাষ্ট্রটিকে কোনও লক রাখার অনুমতি দেওয়া যায় না, কারণ এর কোনও গ্যারান্টি নেই যে ব্যবহারকারীর কোডটি সিস্কলটি আবার চালু করবে এবং তারপরে লকটি চিরতরে ধরে রাখা হবে।
    • সিস্কেল শুরু করতে সাধারণ ইন্টারফেসের পাশাপাশি চলমান সিস্টেমেগুলি পুনরায় শুরু করতে বা বাতিল করতে কার্নেলের অবশ্যই নতুন ইন্টারফেস প্রকাশ করতে হবে। বিরল ক্ষেত্রে এটি অনেক জটিলতা।
    • সংরক্ষিত রাষ্ট্রের রিসোর্স (মেমরি, কমপক্ষে) ব্যবহার করা প্রয়োজন; এই সংস্থানগুলি কার্নেল দ্বারা বরাদ্দ এবং ধরে রাখা দরকার তবে প্রক্রিয়া বরাদ্দের বিপরীতে গণনা করা হবে। এটি দুর্গম নয়, তবে এটি একটি জটিলতা।
      • মনে রাখবেন যে সিগন্যাল হ্যান্ডলারটি সিস্টেম কল করতে পারে যে তারা নিজেরাই বাধা পেয়েছে; সুতরাং আপনার কেবলমাত্র একটি স্থিতিশীল সংস্থান বরাদ্দ থাকতে পারে না যা সমস্ত সম্ভাব্য স্কাইলকে কভার করে।
      • আর যদি সম্পদ বরাদ্দ না করা যায় তবে কী হবে? তাহলে সিস্কেলকে যাইহোক ব্যর্থ হতে হবে। যার অর্থ এই ক্ষেত্রে পরিচালনা করার জন্য অ্যাপ্লিকেশনটির কোড থাকা দরকার, সুতরাং এই নকশাটি অ্যাপ্লিকেশন কোডটিকে সহজতর করবে না।
  • প্রগতিতে থাকুন (তবে স্থগিত), সিগন্যাল হ্যান্ডলারের জন্য একটি নতুন থ্রেড তৈরি করুন। এটি আবার সমস্যাযুক্ত:
    • প্রথমদিকে ইউনিক্স বাস্তবায়নের ক্ষেত্রে প্রক্রিয়া অনুযায়ী একক থ্রেড ছিল।
    • সিগন্যাল হ্যান্ডলারটি সিস্কলের জুতাগুলি ছাড়িয়ে যাওয়ার ঝুঁকি ফেলবে। এটি যাইহোক সমস্যা, তবে বর্তমান ইউনিক্স ডিজাইনে এটি রয়েছে।
    • নতুন থ্রেডের জন্য সংস্থানগুলি বরাদ্দ করা দরকার; উপরে দেখুন.

একটি বিঘ্নের সাথে প্রধান পার্থক্য হ'ল বিঘ্নিত কোডটি বিশ্বস্ত, এবং অত্যন্ত সীমাবদ্ধ। এটিকে সাধারণত সম্পদ বরাদ্দ করতে, বা চিরকালের জন্য চালানো, বা তালা নেওয়া এবং সেগুলি ছেড়ে না দেওয়া, বা অন্য কোনও ধরনের বাজে কাজ করার অনুমতি নেই; যেহেতু বিঘ্নিত হ্যান্ডলারটি ওএস প্রয়োগকারী নিজে লিখেছেন, তিনি জানেন যে এটি কোনও খারাপ কাজ করবে না। অন্যদিকে, অ্যাপ্লিকেশন কোড যে কোনও কিছু করতে পারে।

অ্যাপ্লিকেশন ডিজাইন দেখুন

সিস্টেম কলের মাঝে যখন কোনও অ্যাপ্লিকেশন বাধাগ্রস্ত হয়, তখন সিস্কালটি সমাপ্তি অব্যাহত রাখা উচিত? সবসময় না। উদাহরণস্বরূপ, শেলের মতো একটি প্রোগ্রাম বিবেচনা করুন যা টার্মিনাল থেকে একটি লাইন পড়ছে এবং ব্যবহারকারীরা Ctrl+Cসিগিন্টকে ট্রিগার করে। পঠন অবশ্যই শেষ হবে না, এটিই সিগন্যাল সম্পর্কে। নোট করুন যে এই উদাহরণটি দেখায় যে readসাইকেলটি অবশ্যই বাধা পড়তে হবে যদিও কোনও বাইট এখনও পড়ে না।

সুতরাং অ্যাপ্লিকেশনটির জন্য কার্নেলটিকে সিস্টেম কলটি বাতিল করতে বলার একটি উপায় থাকতে হবে। ইউনিক্স ডিজাইনের অধীনে এটি স্বয়ংক্রিয়ভাবে ঘটে: সংকেত সিস্কলকে ফিরে দেয়। অন্যান্য ডিজাইনের জন্য অ্যাপ্লিকেশনটির পুনরুদ্ধার করার বা পুনরুদ্ধার করার জন্য স্ক্যাসকাল বাতিল করার জন্য একটি উপায় প্রয়োজন।

readসিস্টেম কল তার কারণ হল, এটা আদিম যে অর্থে তোলে যে, অপারেটিং সিস্টেমের সাধারণ নকশা দেওয়া উপায়। এর অর্থ হ'ল মোটামুটি, "আপনি যতটা পারেন সীমাতে (বাফার সাইজ) পড়ুন, তবে অন্য কিছু ঘটলে থামুন" ” একটি সম্পূর্ণ বাফার পড়ার জন্য readযতটা সম্ভব বাইট না পড়া পর্যন্ত একটি লুপে চলমান জড়িত ; এটি একটি উচ্চ-স্তরের ফাংশন fread(3),। read(2)যা সিস্টেম কল হিসাবে ভিন্ন , freadএটি একটি লাইব্রেরি ফাংশন, এর উপরে ব্যবহারকারী স্থানে প্রয়োগ করা হয় read। এটি এমন কোনও অ্যাপ্লিকেশনের জন্য উপযুক্ত যা কোনও ফাইলের জন্য পড়ে বা চেষ্টা করে মারা যায়; এটি কোনও কমান্ড লাইন ইন্টারপ্রেটার বা এমন একটি নেটওয়ার্ক প্রোগ্রামের জন্য উপযুক্ত নয় যা অবশ্যই সংযোগগুলি পরিষ্কারভাবে থ্রটল করতে হবে, বা এমন একটি নেটওয়ার্ক প্রোগ্রামের জন্য নয় যা সামঞ্জস্যপূর্ণ সংযোগ রয়েছে এবং থ্রেড ব্যবহার করে না।

একটি লুপে পড়ার উদাহরণ রবার্ট লাভের লিনাক্স সিস্টেম প্রোগ্রামিংয়ে সরবরাহ করা হয়েছে:

ssize_t ret;
while (len != 0 && (ret = read (fd, buf, len)) != 0) {
  if (ret == -1) {
    if (errno == EINTR)
      continue;
    perror ("read");
    break;
  }
  len -= ret;
  buf += ret;
}

এটা তোলে যত্ন নেয় case iএবং case iiকয়েক আরও অনেক কিছু।


খুব সংক্ষিপ্ত এবং স্পষ্ট উত্তরের জন্য গিলসকে অনেক ধন্যবাদ, যা ইউনিক্স ডিজাইন দর্শনের উপর একটি নিবন্ধে অনুরূপ মতামতকে সামনে রেখে দিয়েছে। আমার কাছে খুব
দৃinc়প্রত্যয় বলে

@दरবেহদার এটি তিনটিই: ইউনিক্স ডিজাইনের দর্শন (এখানে মূলত যে প্রক্রিয়াগুলি কার্নেলের চেয়ে কম বিশ্বাসযোগ্য এবং প্রক্রিয়াগুলি এবং থ্রেডগুলি স্পষ্টভাবে তৈরি করা হয় না), প্রযুক্তিগত বাধা (সংস্থার বরাদ্দের উপর) এবং অ্যাপ্লিকেশন ডিজাইন (সেখানে সিগন্যাল সিস্টেমে বাতিল করা আবশ্যক ক্ষেত্রে)।
গিলস 7'১

2

প্রশ্নের উত্তর দিতে :

হ্যাঁ, সিগন্যালের বিতরণ ও পরিচালনা পুরোপুরি স্বচ্ছ নয় read()

এই read()সংকেত দ্বারা বাধাগ্রস্থ হওয়ার পরে অর্ধেকটি চলমান কিছু সংস্থান দখল করতে পারে। এবং সিগন্যালের সিগন্যাল হ্যান্ডলার অন্যটিকেread() (বা অন্য কোনও এসিঙ্ক-সিগন্যাল নিরাপদ সিস্কল ) কল করতে পারে । সুতরাং read()এটি ব্যবহার করা সংস্থানগুলি প্রকাশের জন্য প্রথমে সংকেত দ্বারা বাধাগুলি বন্ধ করতে হবে, অন্যথায় read()সিগন্যাল হ্যান্ডলার থেকে কল করা একই সংস্থানগুলিতে অ্যাক্সেস করবে এবং পুনরায় সমস্যার সমাধান করবে।

কারণ সিস্টেম কল ছাড়াও অন্যান্য কলগুলি read()সিগন্যাল হ্যান্ডলার থেকে কল করা যেতে পারে এবং তারা একই ধরণের সংস্থানগুলিও দখল করতে read()পারে। উপরের প্রবণতা সংক্রান্ত সমস্যাগুলি এড়াতে, সবচেয়ে সহজ, নিরাপদ ডিজাইনটি read()প্রতিবার যখন সংকেত চলার সময় ঘটে তখন বাধা দেওয়া বন্ধ করে দেওয়া হয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.