WriteFile সফল ফেরাল। তো, ডেটা এখন কোথায়?
উত্তর, প্রায় নিশ্চিত এখনও ডিস্কে নেই। মেমরির ক্যাশে কপি হয়েছে মাত্র। তাই «সেভ করলাম, পাওয়ার কাটের পর ফিরে দেখি গেছে» ঘটে; তাই ফাইল কপির বেঞ্চমার্ক ভৌতভাবে অসম্ভব গতি দেখায়; তাই ডেটাবেস নিষ্ঠার সঙ্গে fsync ডাকে।
ধারাবাহিক «Windows I/O-এর গভীরতা»-এর ৪র্থ কিস্তি, এই মাঝে দাঁড়ানো ক্যাশ ম্যানেজার। ২য় কিস্তি-এ «ক্যাশে থাকলে অ্যাসিঙ্ক্রোনাস I/O-ও সিঙ্ক্রোনাসে শেষ হয়» লিখেছি, ১ম কিস্তি-তে «IRP না বানানো ছোট পথ (ফাস্ট I/O)» বাড়ির কাজ রেখেছি। এবার সেই সূত্র সব তুলে আনি।
1. আগে উপসংহার
- Windows-এর ফাইল ক্যাশ রাইট-ব্যাক পদ্ধতি। পড়া আগে সিস্টেম ফাইল ক্যাশ থেকে, লেখাও আগে ক্যাশে। ডিস্কে প্রতিফলন OS পরে করে।1
- ক্যাশের সত্তা ফাইল ম্যাপিং। ক্যাশ ম্যানেজার ফাইলের 256KB খণ্ড সিস্টেমের অ্যাড্রেস স্পেসে ম্যাপ করে, পড়া-লেখা «সেই ভিউয়ের সঙ্গে মেমরি কপি» হয় (২ অধ্যায়)।1
- লেখা প্রতি সেকেন্ডের বিলম্বিত লেখা (lazy writer) পেছন থেকে প্রতিফলিত করে। অ্যাপ ক্র্যাশে ডেটা হারায় না, কিন্তু পাওয়ার কাট বা OS ক্র্যাশে ডার্টি ক্যাশ হারায় (৪ অধ্যায়)।1
- «নিশ্চিত লেখা»র সরঞ্জাম তিনটে।
FlushFileBuffers(= .NET-এরFlush(true)),FILE_FLAG_WRITE_THROUGH,FILE_FLAG_NO_BUFFERING। ঘন ঘন লেখায় প্রতিবার ফ্লাশ অদক্ষ, সরকারি নথি NO_BUFFERING+WRITE_THROUGH একসঙ্গে গণনা করে (৫ অধ্যায়)।21 - NO_BUFFERING-এ সারিবদ্ধতার শর্ত আছে। আকার·অফসেট সেক্টর আকারের পূর্ণ গুণিতক, বাফার ঠিকানাও ভৌত সেক্টর সীমায় সারিবদ্ধ। আর NO_BUFFERING-এও মেটাডেটা ক্যাশ হতেই থাকে (৫.৩ অনুচ্ছেদ)।31
- ম্যাপ ভিউ ও ক্যাশ একই ডেটা ভাগ করে। মেমরি-ম্যাপড ফাইল ও সাধারণ ক্যাশ I/O সামঞ্জস্যপূর্ণ, ম্যাপের স্থায়িত্ব
FlushViewOfFile+FlushFileBuffersদুই ধাপ (৬ অধ্যায়)।45 - ক্যাশে থাকা সিঙ্ক্রোনাস পড়া-লেখা IRP-ও নাও বানাতে পারে। ফাস্ট I/O নামের ছোট পথ ক্যাশ ম্যানেজারে সোজা যায় — ১ম কিস্তির বাড়ির কাজের উত্তর (৭ অধ্যায়)।6
এই নিবন্ধের জ্ঞান মানচিত্র
WriteFile সফল মানে ডিস্কে স্থায়ী হওয়া নয়; Windows-এর ফাইল ক্যাশ আগে সিস্টেম ক্যাশ ভিউতে কপি করে, ডিস্কে প্রতিফলন lazy writer প্রতি সেকেন্ডে পেছন থেকে ধরে। বিদ্যুৎ বিচ্ছিন্নতা বা OS ক্র্যাশে এখনও না-লেখা ডার্টি পেজ হারিয়ে যায়, তাই নিশ্চিত করে লিখতে চাওয়া ডেটায় FlushFileBuffers · FILE_FLAG_WRITE_THROUGH · FILE_FLAG_NO_BUFFERING আলাদা করে ব্যবহার করতে হয়।
flowchart LR
accTitle: ক্যাশ ম্যানেজার ও রাইট-বিহাইন্ডের জ্ঞান মানচিত্র
accDescr: ক্যাশ ম্যানেজার, রাইট-ব্যাক ক্যাশ, 256KB সিস্টেম ক্যাশ ভিউ, আগে থেকে পড়া, lazy writer-এর বিলম্বিত লেখা, বিদ্যুৎ বিচ্ছিন্নতায় ডার্টি পেজ হারানো, FlushFileBuffers · FILE_FLAG_WRITE_THROUGH · FILE_FLAG_NO_BUFFERING দিয়ে নিশ্চিত লেখা, অ্যালাইনমেন্টের শর্ত, মেমোরি-ম্যাপড ফাইলের সঙ্গে সামঞ্জস্য, ফাস্ট I/O-এর সম্পর্ক দেখানো চিত্র
cache_manager["ক্যাশ ম্যানেজার"]
write_behind_caching["রাইট-ব্যাক ক্যাশ (বিলম্বিত লেখার পদ্ধতি)"]
memory_mapped_file["ফাইল ম্যাপিং (মেমোরি-ম্যাপড ফাইল)"]
system_cache_view["সিস্টেম ক্যাশ ভিউ (256KB স্লট)"]
file_object["ফাইল অবজেক্ট"]
lazy_writer["lazy writer (বিলম্বিত লেখার থ্রেড)"]
unflushed_write_loss["অপ্রতিফলিত ডেটার ক্ষতি"]
temp_file_attribute["FILE_ATTRIBUTE_TEMPORARY"]
dirty_page["ডার্টি পেজ"]
power_loss["বিদ্যুৎ বিচ্ছিন্নতা · OS ক্র্যাশ"]
read_ahead["আগে থেকে পড়া (read-ahead)"]
sequential_scan_hint["FILE_FLAG_SEQUENTIAL_SCAN"]
random_access_hint["FILE_FLAG_RANDOM_ACCESS"]
flushfilebuffers["FlushFileBuffers"]
write_through["FILE_FLAG_WRITE_THROUGH"]
no_buffering["FILE_FLAG_NO_BUFFERING"]
sector_alignment_requirement["সেক্টর অ্যালাইনমেন্টের শর্ত"]
invalid_parameter_error["ERROR_INVALID_PARAMETER (87)"]
frequent_durable_write["ঘন লেখায় নিশ্চিত স্থায়িত্ব"]
flushviewoffile["FlushViewOfFile"]
fast_io["ফাস্ট I/O"]
procmon["Process Monitor (procmon.exe)"]
irp["IRP (I/O অনুরোধ প্যাকেট)"]
synchronous_io["সিঙ্ক্রোনাস I/O"]
cache_manager -->|"বাস্তবায়ন করে"| write_behind_caching
write_behind_caching -->|"ব্যবহার করে"| memory_mapped_file
cache_manager -->|"ব্যবহার করে"| system_cache_view
system_cache_view -->|"ব্যবহার করে"| memory_mapped_file
cache_manager -->|"ব্যবহার করে"| file_object
cache_manager -->|"ব্যবহার করে"| lazy_writer
lazy_writer -->|"স্বয়ংক্রিয় করে"| write_behind_caching
lazy_writer -->|"কমায়"| unflushed_write_loss
temp_file_attribute -.->|"সামঞ্জস্যহীন"| lazy_writer
write_behind_caching -->|"কারণ হতে পারে"| dirty_page
dirty_page -->|"এ সংরক্ষিত"| system_cache_view
power_loss -.->|"কারণ হতে পারে"| unflushed_write_loss
cache_manager -.->|"প্রতিরোধ করে"| unflushed_write_loss
cache_manager -->|"ব্যবহার করে"| read_ahead
read_ahead -.->|"দিয়ে কনফিগার"| sequential_scan_hint
read_ahead -.->|"দিয়ে কনফিগার"| random_access_hint
flushfilebuffers -->|"প্রতিরোধ করে"| unflushed_write_loss
write_through -->|"প্রতিরোধ করে"| unflushed_write_loss
no_buffering -.->|"কমায়"| unflushed_write_loss
no_buffering -->|"পূর্বশর্ত"| sector_alignment_requirement
sector_alignment_requirement -->|"প্রতিরোধ করে"| invalid_parameter_error
no_buffering -->|"কারণ হতে পারে"| invalid_parameter_error
flushfilebuffers -->|"ব্যবহার নিরুৎসাহিত"| frequent_durable_write
no_buffering -->|"প্রস্তাবিত সমাধান"| frequent_durable_write
write_through -->|"প্রস্তাবিত সমাধান"| frequent_durable_write
no_buffering -->|"সামঞ্জস্যহীন"| system_cache_view
flushviewoffile -->|"পূর্বশর্ত"| memory_mapped_file
flushviewoffile -->|"আগে করা উচিত"| flushfilebuffers
fast_io -->|"দিয়ে যাচাই"| procmon
fast_io -->|"পূর্বশর্ত"| system_cache_view
fast_io -->|"সামঞ্জস্যহীন"| irp
fast_io -->|"পূর্বশর্ত"| synchronous_io
চিত্রে, টানা রেখা সবসময় সত্য এমন সম্পর্ককে এবং ভাঙা রেখা শর্তসাপেক্ষ সম্পর্ককে নির্দেশ করে (শর্তগুলো বিস্তারিত পাতায় প্রতিটি সম্পর্কের ব্যাখ্যায় আছে)। সম্পর্কের সম্পূর্ণ তালিকা (মোট 32, প্রমাণ ও নিশ্চয়তার মাত্রাসহ) এবং প্রধান ধারণাগুলোর সংজ্ঞা জ্ঞান মানচিত্রের বিস্তারিত পাতায় সংগ্রহ করা আছে (জাপানি ভাষায়)। তথ্য: JSON-LD / Turtle
2. ক্যাশের আসল রূপ — ফাইল মেমরিতে ম্যাপ হয়
2.1. 256KB স্লট ও মেমরি কপি
Windows-এর ফাইল ক্যাশকে «ডিস্ক ব্লকের পাত্র» ভাবলে নানা আচরণ ব্যাখ্যা যায় না। সঠিক ছবি এটা — ক্যাশ ম্যানেজার ফাইলের 256KB খণ্ড সিস্টেম অ্যাড্রেস স্পেসের «স্লট»-এ ম্যাপ করে, ক্যাশ-চালু পড়া-লেখা সেই স্লট ও অ্যাপের বাফারের মাঝে মেমরি কপি হিসেবে চলে।1
flowchart TB
subgraph U["অ্যাপ (ইউজার মোড)"]
BUF["অ্যাপের বাফার<br/>(ReadFile/WriteFile-এ দেওয়া জায়গা)"]
end
subgraph S["সিস্টেম অ্যাড্রেস স্পেস"]
SLOT["সিস্টেম ফাইল ক্যাশ<br/>ফাইলের 256KB খণ্ড ম্যাপ করা স্লট"]
end
DISK[("ডিস্কের ফাইল")]
BUF <-->|"ReadFile/WriteFile =<br/>স্লটের সঙ্গে মেমরি কপি"| SLOT
SLOT <-->|"প্রথম অ্যাক্সেসে পড়া ও<br/>পরে ফেরত লেখা পেজ এককে"| DISK
চিত্র ১: ক্যাশ-চালু I/O-এর আসল ছবি। অ্যাপ থেকে দেখা «ফাইল পড়া-লেখা» বেশিরভাগ সময় শুধু মেমরি কপি
ভুল বোঝার একটা জায়গা। 256KB ভিউ (ম্যাপ)-এর বিভাজন একক, ডিস্ক I/O সবসময় 256KB এককে চলে এমন অর্থ নয়। স্লটের ভিতরের পেজ দরকারমতো পড়া হয়, সত্যি ডিস্কে যাওয়া I/O-এর পরিমাণ অনুরোধের আকার ও অ্যাক্সেস প্যাটার্ন অনুযায়ী বদলায়। প্রথমবার পড়া খণ্ড হলে ভরতে ডিস্ক I/O হয় (এখানে ১ম কিস্তির IRP নিচের স্টোরেজ স্ট্যাকে যায়)। আগে থেকে ক্যাশে থাকলে পড়া শুধু কপিতেই শেষ হয়। ২য় কিস্তি ৫ অধ্যায়-এ দেখা «ক্যাশ হিট হলে অ্যাসিঙ্ক্রোনাস ইস্যু করলেও সিঙ্ক্রোনাসে শেষ হয়» — এটাই «তৎক্ষণাৎ উত্তর দেওয়া যায় এমন অনুরোধ সেখানেই শেষ করা» চালের প্রকাশ। উল্টে, ক্যাশ-চালু রেখে পেজ মেমরিতে না থাকলে পেজ ফল্ট প্রক্রিয়ায় অ্যাসিঙ্ক্রোনাস ব্যবস্থা নেই বলে অ্যাসিঙ্ক্রোনাস পড়া সিঙ্ক্রোনাসে সামলানো হতে পারে — এই ফাঁদও ২য় কিস্তিতে দেখেছি।7
2.2. «খালি মেমরি কমল»-এর আসল রূপ
ক্যাশ ব্যবহার হবে কি না ও আগে পড়ার অবস্থা খোলার ধরন অনুযায়ী (ফাইল অবজেক্ট এককে) সামলানো হয়1, কিন্তু ক্যাশ করা ডেটা নিজে ফাইল (স্ট্রিম) এককে ভাগ হয়। একই ফাইল বারবার খুললে আলাদা ক্যাশ হয় না, যেকোনো হ্যান্ডেল থেকে একই ক্যাশের ভিতর দেখা যায় (৬ অধ্যায়ের সামঞ্জস্যের ভিত্তি)। ক্যাশ Windows চলাকালীন ক্যাশ ম্যানেজারের নেতৃত্বেই চলে।1 বড় ফাইল কপি করলে বা প্রচুর পড়া-লেখা করলে খালি ভৌত মেমরি ক্রমে ক্যাশে বদলে যায়। টাস্ক ম্যানেজারের খালি মেমরি কম দেখালেও তার অনেকটা «অ্যাপ চাইলে তাড়াতাড়ি ছেড়ে দেওয়া যায়, মূল্যবান কাজে লাগানো স্ট্যান্ডবাই মেমরি»। মেমরি কম নির্ণয়ে এই ভাগ ভুল না করতে পর্যবেক্ষণের বাস্তব «.NET-এ GC অপেক্ষা ও মেমরি লিক আলাদা করা»-তেও আছে।
এই চাল পর্দায় নিশ্চিত করা যায়। টাস্ক ম্যানেজার > পারফরম্যান্স > মেমরি খুললে নিচের «মেমরির গঠন» বার ব্যবহারে / পরিবর্তিত / স্ট্যান্ডবাই / খালি-তে ভাগ। ফাইল ক্যাশের বেশিরভাগ এই স্ট্যান্ডবাই-তে যায়, ডানদিকের তালিকায় «ক্যাশ করা» হিসেবে যোগ হয়। আরও সূক্ষ্ম দেখতে রিসোর্স মনিটর > মেমরি ট্যাবে একই ভাগ পরিমাণসহ পাশাপাশি থাকে। কয়েক GB-এর এক ফাইল কপি করে আবার দেখুন — স্ট্যান্ডবাই বাড়ে খালি কমে, «ব্যবহারে» প্রায় বদলায় না — অর্থাৎ «মেমরি খেয়ে ফেলা হয়েছে» নয় «খালি মেমরি ক্যাশে ব্যবহার হয়েছে» চোখেই নিশ্চিত হয়।
3. আগে পড়া — পড়ার অনুমান
ক্যাশ ম্যানেজার অতীত অ্যাক্সেস প্যাটার্ন থেকে পরের যে খণ্ড পড়া যেতে পারে সেটা আগে পড়ে রাখে (read-ahead)। ক্রমে পড়া ফাইলে অ্যাপ চাওয়ার আগেই পরের ডেটা ক্যাশে থাকে — এটাই সিকোয়েন্সিয়াল পড়ার গতির রহস্য ফাঁস। আগে পড়ার পরিমাণ স্থির নয়, শনাক্ত প্যাটার্ন ও অনুরোধের আকার অনুযায়ী বদলায়।
flowchart LR
A["অ্যাপের পড়ার অনুরোধের ইতিহাস<br/>শুরু থেকে ক্রমে পড়ছে"]
D{"ক্যাশ ম্যানেজার<br/>প্যাটার্ন শনাক্ত করে"}
R["আগে পড়া: পরের খণ্ড<br/>চাওয়ার আগে পড়ে রাখে<br/>(পরিমাণ প্যাটার্ন ও অনুরোধ আকার অনুযায়ী বদলায়)"]
H1["ইঙ্গিত FILE_FLAG_SEQUENTIAL_SCAN<br/>= আগে পড়া জোরালোভাবে"]
H2["ইঙ্গিত FILE_FLAG_RANDOM_ACCESS<br/>= আগে পড়া অপচয়, তাই চাপা"]
A --> D
D --> R
H1 -.-> D
H2 -.-> D
চিত্র ২: আগে পড়া। অ্যাক্সেস প্যাটার্ন শনাক্তের সঙ্গে CreateFile-এর ফ্ল্যাগ দিয়ে ইঙ্গিত দেওয়া যায়
১ম কিস্তির মিল সারণিতে থাকা FileOptions.SequentialScan / RandomAccess এই আগে পড়া ইঞ্জিনের ইঙ্গিত। «সব চেটে যাওয়া» ব্যাচ প্রক্রিয়ায় আগেরটা, ইনডেক্স ঘোরার মতো অ্যাক্সেসে পরেরটা — অ্যাপই জানে এমন ভবিষ্যৎ OS-কে জানানোর ফ্ল্যাগ ভাবলে ব্যবহারের জায়গা স্পষ্ট হয়।
4. বিলম্বিত লেখা — WriteFile-এর «সফল»-এর অর্থ
4.1. lazy writer প্রতি সেকেন্ডে আসে
লেখার দিক রাইট-ব্যাক ক্যাশ। WriteFile ডেটা স্লটে কপি হওয়ার মুহূর্তেই সফল ফেরায়, ডিস্কে প্রতিফলন পরে। এই «দেরি করে লেখা» নীতিই বিলম্বিত লেখা (lazy writing)।1
প্রতিফলন চালায় ক্যাশ ম্যানেজার প্রতি সেকেন্ডে চালু করা lazy writer। সম্প্রতি ফ্লাশ হয়নি এমন পেজের ৮ ভাগের ১ ভাগ কিউতে তুলে লেখে, লেখার মতো ডেটা বেশি হলে আরও বাড়ায়। আর FILE_ATTRIBUTE_TEMPORARY অ্যাট্রিবিউট দিয়ে বানানো অস্থায়ী ফাইল lazy writer-এর ফ্লাশ লক্ষ্য থেকে বাদ — শিগগির মুছে যাবে ধরে নিয়ে লেখা অপচয়।1 তবে এটা অ্যাট্রিবিউটের ইঙ্গিত, মেমরি টান পড়লে ফেরত লেখা হতেই পারে, আর «নাম শুধু অস্থায়ী-মতো» ফাইলে লাগে না।
sequenceDiagram
participant App as অ্যাপ
participant C as সিস্টেম ক্যাশ
participant LW as lazy writer (প্রতি সেকেন্ডে চালু)
participant D as ডিস্ক
App->>C: WriteFile(ডেটা)
Note over C: স্লটে কপি করে<br/>পেজ ডার্টি (আনলিখিত) করে
C-->>App: সঙ্গে সঙ্গে TRUE ফেরে
Note over App,C: এখান থেকে ফেরত লেখা পর্যন্ত «বিপজ্জনক জানালা»<br/>পাওয়ার কাট·OS ক্র্যাশে এই ডেটা হারায়
LW->>C: ডার্টি পেজের 1/8 বেছে নেয়
LW->>D: একসঙ্গে ফেরত লেখে
Note over D: এখানেই প্রথম স্থায়ী হয়
চিত্র ৩: বিলম্বিত লেখা। WriteFile-এর সফল «OS-এর হাতে তুলে দিয়েছে», «স্থায়ী হয়েছে» নয়
4.2. কী ঘটলে কতদূর হারায়
«বিপজ্জনক জানালা»-র অর্থ সঠিক করি। বিঘ্নের ধরনে ভাগ্য ভাগ হয়।
flowchart TB
W["WriteFile সফলের ঠিক পরের ডেটা<br/>(ক্যাশের ডার্টি পেজ)"]
Q{"কী ঘটেছে"}
A1["অ্যাপের প্রসেস<br/>ক্র্যাশ/জোর করে শেষ"]
A2["OS-সহ থেমে যাওয়া<br/>(পাওয়ার কাট·ব্লু স্ক্রিন)"]
S["ডেটা থাকে<br/>ক্যাশ OS-এর তাই<br/>lazy writer নির্ধারিতমতো ফেরত লেখে"]
L["ডার্টি পেজ হারায়<br/>ডিস্কে পৌঁছানো অংশই থাকে"]
W --> Q
Q --> A1
Q --> A2
A1 --> S
A2 --> L
চিত্র ৪: বিঘ্নের ধরন ও বেঁচে থাকার ভাগরেখা। ক্যাশ «প্রসেসের সম্পত্তি» নয় «OS-এর সম্পত্তি»
- অ্যাপ মরলেও ডেটা হারায় না। ক্যাশে কপি শেষ হওয়ার মুহূর্তে ডেটার মালিক OS। «সেভের ঠিক পরে অ্যাপ পড়ে গেল তবু ফাইল অক্ষত» এজন্যই।
- OS-সহ মরলে ডার্টি অংশ হারায়। ফ্লাশের ঘনত্ব পারফরম্যান্স ও নির্ভরযোগ্যতার আপস হিসেবে সমন্বয় করা, «হঠাৎ পাওয়ার হারালে ক্যাশ করা ডেটা হারায়» নথিতেও স্পষ্ট।1
অর্থাৎ ব্যবসায়িক অ্যাপের নকশার প্রশ্ন, «এই ডেটা পাওয়ার কাটের মুহূর্তে হারালে চলে কি»। লগের কয়েক সেকেন্ড হয়তো চলতে পারে। অর্ডার ডেটার নিশ্চিত রেকর্ড চলবে না। যা চলে না শুধু তাতেই পরের অধ্যায়ের সরঞ্জাম ব্যবহার করুন।
5. «নিশ্চিত লেখা» বানানোর সরঞ্জাম বাক্স
5.1. FlushFileBuffers — এখনই লিখে শেষ করুন
FlushFileBuffers নির্দিষ্ট ফাইলের বাফার করা ডেটা ডিভাইস পর্যন্ত লিখে শেষ করে। ফাইল সিস্টেমের মেটাডেটা সবসময় ক্যাশ হয়, তাই মেটাডেটা পর্যন্ত নিশ্চিত পৌঁছাতে ফ্লাশ (বা WRITE_THROUGH) লাগে — এটাও ধরার জায়গা।12 .NET-এ FileStream.Flush(true) এর সমতুল্য (Flush() একা শুধু .NET-এর ভিতরের বাফার OS-এ দেয়, OS-এর ক্যাশ যেমন ছিল তেমনই থাকে)।8
তবে সরকারি নথি স্পষ্ট পেরেক মারে — প্রতি লেখায় প্রতিবার ডাকা অদক্ষ। অনেক লেখায় প্রতিবার স্থায়িত্ব লাগলে পরে বলা NO_BUFFERING+WRITE_THROUGH ব্যবহার করা উচিত।2
5.2. FILE_FLAG_WRITE_THROUGH — শুধু দেরি সরানো
FILE_FLAG_WRITE_THROUGH দিয়ে খুললে লেখা ক্যাশেও লেখা হয়, lazy writer-এর অপেক্ষা না করে সঙ্গে সঙ্গে ডিস্কেও লেখা হয়।1 পড়া এখনও ক্যাশের সুবিধা পায় — «পড়া দ্রুত থাকুক, লেখার দেরিই সরাক»-এর সরল উত্তর।
5.3. FILE_FLAG_NO_BUFFERING — ক্যাশ পেরোয় না
FILE_FLAG_NO_BUFFERING পড়া-লেখা থেকে সিস্টেম ক্যাশ নিজেই বাদ দেয়। সব পড়া-লেখা ক্যাশ না পেরিয়ে প্রতিবার ডিস্ক ডিভাইসে I/O হয়।1 তবে পেরোতে পারে Windows-এর সিস্টেম ক্যাশ পর্যন্ত, চিত্র ৫ অনুযায়ী ডিভাইসের ভিতরের লেখার ক্যাশ আলাদা ধাপ। পাওয়ার কাট সহ্য পর্যন্ত চাইলে WRITE_THROUGH একসঙ্গে বা FlushFileBuffers এখনও লাগে। প্রচুর ডেটার একগুচ্ছ স্থানান্তর বা নিজে বাফার সামলানো ডেটাবেস ইঞ্জিনের সরঞ্জাম, কিন্তু কঠোর অঙ্গীকার লাগে।3
- পড়া-লেখার আকার ও ফাইল অফসেট ভলিউমের সেক্টর আকারের পূর্ণ গুণিতক (512 বাইট সেক্টরে 512·1024·1536…)।
- বাফারের ঠিকানাও ভৌত সেক্টর আকারে সারিবদ্ধ (4096 বাইট ভৌত সেক্টরের «Advanced Format» ডিস্কের খেয়ালও লাগে)।
- তবু মেটাডেটা ক্যাশ হতেই থাকে, পূর্ণ স্থায়িত্বে WRITE_THROUGH একসঙ্গে বা
FlushFileBuffersলাগে।12
এই «অঙ্গীকার» ফ্ল্যাগ জুড়েই সারা যাবে ভেবে যে আগে পড়ে। সারিবদ্ধতা না মেনে পড়া-লেখা করলে ERROR_INVALID_PARAMETER (87) দিয়ে ব্যর্থ হয়। মানতে হবে এমন তিনটে বিষয় সাজাই।3
| যা মিলাতে হবে | শর্ত | কীভাবে মেটাবেন |
|---|---|---|
| পড়া-লেখার আকার | ভলিউমের সেক্টর আকারের পূর্ণ গুণিতক | GetDiskFreeSpace-এর lpBytesPerSector নিয়ে সেই গুণিতকে গোল করুন |
| ফাইল অফসেট | একই (OVERLAPPED-এর Offset দিলেও) |
সেক্টর আকারের গুণিতক করে এগোন |
| বাফারের ঠিকানা | ভৌত সেক্টর আকারে সারিবদ্ধ | VirtualAlloc দিয়ে বরাদ্দ করুন (পেজ সীমা = সাধারণত 4096 বাইটে সারিবদ্ধ জায়গা ফেরে) |
তৃতীয়টা বিশেষ করে ছুটে যায়। malloc বা new, C#-এর অ্যারে যে ঠিকানা ফেরায় তাতে সেক্টর সীমায় সারিবদ্ধতার নিশ্চয়তা নেই। পেজ সীমায় বরাদ্দ করা VirtualAlloc ব্যবহার করলে ভৌত সেক্টর 4096 বাইটের «Advanced Format» ডিস্কের শর্তও একসঙ্গে মেটে। সবচেয়ে ছোট রূপ এমন।
// C++ / Win32। ত্রুটি সামলানো ন্যূনতম রাখা
DWORD sectorsPerCluster = 0, bytesPerSector = 0, freeClusters = 0, totalClusters = 0;
if (!GetDiskFreeSpaceW(L"C:\\", §orsPerCluster, &bytesPerSector,
&freeClusters, &totalClusters))
{
return GetLastError();
}
// পড়া-লেখার একক সেক্টর আকারের পূর্ণ গুণিতক করা (এখানে প্রায় 1MiB)
const DWORD chunk = (1024 * 1024 / bytesPerSector) * bytesPerSector;
// বাফার পেজ সীমায় সারিবদ্ধ জায়গা নেওয়া (malloc/new-এ নিশ্চয়তা নেই)
BYTE* buffer = static_cast<BYTE*>(
VirtualAlloc(nullptr, chunk, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
if (buffer == nullptr) { return GetLastError(); }
HANDLE h = CreateFileW(L"C:\\temp\\big.bin", GENERIC_READ, FILE_SHARE_READ, nullptr,
OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, nullptr);
if (h == INVALID_HANDLE_VALUE)
{
// GetLastError «ঠিক আগের Win32 কল»-এর ফল ফেরায়। আগে VirtualFree
// ডাকলে CreateFileW-এর ব্যর্থতার কারণ (অ্যাক্সেস অস্বীকার·পাথ নেই ইত্যাদি)
// পরিষ্কারের ফলে চাপা পড়ে, কারণ না-বোঝা কোডই শুধু ফেরে
const DWORD err = GetLastError();
VirtualFree(buffer, 0, MEM_RELEASE);
return err;
}
// প্রতিবার chunk বাইট করে এগোয় বলে আকারও অফসেটও সারিবদ্ধ থাকে
DWORD read = 0;
while (ReadFile(h, buffer, chunk, &read, nullptr) && read > 0)
{
// buffer-এর শুরুর read বাইট প্রক্রিয়া করুন
// (ফাইল শেষে read < chunk হয়। এটা স্বাভাবিক)
}
CloseHandle(h);
VirtualFree(buffer, 0, MEM_RELEASE);
আর .NET-এর FileOptions-এ FILE_FLAG_NO_BUFFERING-এর সমতুল্য মান নেই। সত্যিই লাগলে CreateFile সরাসরি ডাকতে হয়, তখনও উপরের সারিবদ্ধতার শর্ত নিজে মানতে হয়। «দ্রুত চাই তাই NO_BUFFERING» নয়, «নিজে বাফার সামলাই তাই NO_BUFFERING» — এই ক্রমে ভাবুন।
5.4. ব্যবহার ভাগ সাজানো
flowchart TB
A["অ্যাপের বাফার"]
B["সিস্টেম ফাইল ক্যাশ<br/>(ডার্টি পেজ)"]
C["ডিস্ক ডিভাইসের ভিতরের ক্যাশ"]
D[("অবিচল সংরক্ষণ মাধ্যম")]
A -->|"ডিফল্ট WriteFile: এখান পর্যন্ত সফল ফেরে"| B
B -->|"lazy writer (প্রতি সেকেন্ডে) / WRITE_THROUGH (তৎক্ষণাৎ)"| C
C -->|"ডিভাইসের সময় /<br/>FlushFileBuffers শেষ পর্যন্ত লেখার দাবি করে"| D
A -.->|"NO_BUFFERING ক্যাশ পেরিয়ে সোজা যায়"| C
চিত্র ৫: ডেটার স্তর ও প্রতি সরঞ্জাম কতদূর ঠেলে দেয়। «ডিস্ক ডিভাইসের ভিতরের ক্যাশ» শেষ ধাপও খেয়াল রাখুন
| পদ্ধতি | কী হয় | যেখানে মানায় |
|---|---|---|
| ডিফল্ট (ক্যাশ চালু) | ক্যাশ কপিতে শেষ। প্রতিফলন lazy writer | বেশিরভাগ ফাইল I/O |
FlushFileBuffers / Flush(true) |
সেই মুহূর্তের ডেটা+মেটাডেটা লিখে শেষ | মোড়ে নিশ্চিতকরণ (লেনদেন কমিট ইত্যাদি) |
FILE_FLAG_WRITE_THROUGH |
প্রতি লেখায় সঙ্গে সঙ্গে ডিস্কে (পড়া ক্যাশে) | হারানো চলে না এমন চলমান লগ·জার্নাল |
FILE_FLAG_NO_BUFFERING (+WRITE_THROUGH) |
ক্যাশ ছাড়া। সারিবদ্ধতার শর্ত আছে | নিজের বাফার ব্যবস্থাপনা·বড় একগুচ্ছ I/O |
বাছার ক্রম «পাওয়ার কাটে কত রেকর্ড হারালে চলে» আগে স্থির করুন, তারপর «এজন্য কত ধীর হলে চলে» নিশ্চিত করুন — দুই ধাপ। সারণি উপর থেকে না দেখে এই শাখা ঘুরুন।
flowchart TB
S["এই ডেটা লিখতে যাচ্ছেন"]
Q1{"পাওয়ার কাট·ব্লু স্ক্রিনের মুহূর্তে<br/>হারালেও চলে কি"}
A0["ডিফল্টই রাখুন (ক্যাশ চালু)<br/>সবচেয়ে দ্রুত। বেশিরভাগ I/O এখানে"]
Q2{"হারানো চলে না সেটা<br/>«মোড়» না «প্রতি রেকর্ড»"}
A1["মোড়ে FlushFileBuffers<br/>.NET-এ Flush(true)<br/>খরচ: মোড়ের অপেক্ষাই"]
Q3{"নিজে বাফার সামলান ও<br/>5.3-এর সারিবদ্ধতার শর্ত মেটাতে পারেন কি"}
A2["FILE_FLAG_WRITE_THROUGH<br/>লেখার প্রতিবার সঙ্গে সঙ্গে ডিস্কে<br/>পড়া ক্যাশেই দ্রুত থাকে"]
A3["FILE_FLAG_NO_BUFFERING<br/>+ FILE_FLAG_WRITE_THROUGH<br/>সরকারি «ঘন ঘন স্থায়িত্ব»-এর রূপ"]
S --> Q1
Q1 -->|"চলে<br/>(গত কয়েক সেকেন্ডের লগ ইত্যাদি)"| A0
Q1 -->|"চলে না"| Q2
Q2 -->|"মোড়<br/>(লেনদেন নিশ্চিত ইত্যাদি)"| A1
Q2 -->|"প্রতি রেকর্ড"| Q3
Q3 -->|"না (সাধারণ অ্যাপ)"| A2
Q3 -->|"হ্যাঁ (DB ইঞ্জিন ইত্যাদি)"| A3
চিত্র ৬: সরঞ্জাম বাছা। প্রথম শাখা নির্ভরযোগ্যতার দাবি, দ্বিতীয় যে খরচ দেওয়া যায়। «প্রতি রেকর্ডে FlushFileBuffers» পথ নেই, ৫.১ অনুযায়ী সরকারি নথি তাকে অদক্ষ বলে
বাস্তব প্যাটার্নও তিনটেই গণনা করি।
- «অস্থায়ী ফাইলে লেখা → ফ্লাশ → নাম বদল» ভাঙা ফাইল না রাখার নিয়ম। ভিতর লিখে শেষ করে নাম দিয়ে নিশ্চিত করা — এই পরমাণু হস্তান্তর «ফাইল সহযোগিতার একচেটিয়া নিয়ন্ত্রণের মৌলিক জ্ঞান»-এ বিস্তারিত।
- ডেটাবেসের হাতে দেওয়াও ভালো নকশা। SQLite WAL ও ফ্লাশ দিয়ে স্থায়িত্ব গড়ে তোলে — «C#-এ SQLite ব্যবসায়িক অ্যাপে ব্যবহার» দেখুন। «নিজে ফ্লাশ কৌশল না লেখা» বিকল্প সবসময় টেবিলে আছে।
- বেঞ্চমার্কে ক্যাশ সন্দেহ করুন। «পড়া অতিরিক্ত দ্রুত» মাপ প্রায়ই দ্বিতীয়বারের পরের ক্যাশ হিট মাপে। মাপার রীতি «Windows-এ প্রোগ্রামের সংস্করণভেদে গতি সঠিকভাবে তুলনা করার পদ্ধতি»-তে সাজানো।
চিত্র ৫-এর শেষ ধাপ — ডিস্ক ডিভাইসের ভিতরের ক্যাশও ভুলবেন না। FlushFileBuffers সেখান পর্যন্ত লিখে শেষ করার দাবি করে, কিন্তু USB মেমরি বা বাইরের ডিস্কে ডিভাইস পাশের লেখার ক্যাশ নীতি («দ্রুত সরানো» বনাম «উচ্চ পারফরম্যান্স») জড়ায়। সরানো যায় এমন ডিভাইস সামলানো «Windows অ্যাপে USB ডিভাইস সামলানো»-ও দেখুন।
6. মেমরি-ম্যাপড ফাইলের সঙ্গে সামঞ্জস্য
১ম কিস্তিতে «ক্যাশের সত্তা ফাইল ম্যাপিং» শুনে এমন ভেবে থাকবেন — তাহলে নিজে MapViewOfFile করা ভিউ আর ReadFile/WriteFile-এর ক্যাশ কি লড়ে?
লড়ে না। একই ব্যবস্থার উপর বসে। ফাইল ম্যাপিং অবজেক্ট ফাইলে পিঠ দেয়, পেজ সরানো ফাইলে ফেরত লেখা হিসেবে হয়। একই স্থানীয় ফাইলে একাধিক প্রসেস ভিউ বানালেও দেখা ভিতর সামঞ্জস্যপূর্ণ (কোহেরেন্ট)।4
flowchart TB
subgraph P1["প্রসেস A-এর অ্যাড্রেস স্পেস"]
V1["MapViewOfFile-এর ভিউ"]
end
subgraph SYS["সিস্টেম অ্যাড্রেস স্পেস"]
SC["ক্যাশ ম্যানেজারের ভিউ<br/>(ReadFile/WriteFile যে স্লট ব্যবহার করে)"]
end
PAGES["একই ভৌত পেজসমূহ<br/>(ফাইল-ব্যাকড মেমরি)"]
DISK[("ডিস্কের ফাইল")]
V1 --> PAGES
SC --> PAGES
PAGES --> DISK
NB["FILE_FLAG_NO_BUFFERING-এর I/O<br/>এই ভাগের বাইরে (সোজা ডিস্কে)"]
NB -.-> DISK
চিত্র ৭: ম্যাপ ভিউও ক্যাশও একই «ফাইলে পিঠ দেওয়া পেজ» দেখে। বাইরে শুধু NO_BUFFERING
খেয়াল দুটো।
FILE_FLAG_NO_BUFFERING-এর I/O এই সামঞ্জস্যের বাইরে। ক্যাশ না পেরিয়ে পড়া-লেখা আর ম্যাপ ভিউ/ক্যাশের ভিতর মেলানো হয় না। মেশালে নিজে সামঞ্জস্য রাখতে হয়।- ম্যাপ ভিউয়ের স্থায়িত্ব দুই ধাপ।
FlushViewOfFileপরিসরের ডার্টি পেজ লেখা শুরু করে, কিন্তু মেটাডেটা লেখে না, ডিস্ক ডিভাইসের ক্যাশ থেকে ভৌত লেখাও অপেক্ষা করে না। নিশ্চিত পৌঁছাতেFlushViewOfFile-এর পরFlushFileBuffersডাকুন।5
শেয়ারড মেমরি হিসেবে ফাইল ম্যাপিংয়ের বাস্তব (নামযুক্ত ভাগ, সিঙ্ক, দুর্ঘটনার প্যাটার্ন) «শেয়ারড মেমরির ফাঁদ ও বাস্তব সেরা চর্চা»-তে আছে।
7. ফাস্ট I/O — ১ম কিস্তির বাড়ির কাজ তোলা
আগে দুই লাইন। ফাস্ট I/O ক্যাশে থাকা ফাইলে সিঙ্ক্রোনাস পড়া-লেখার জন্য বানানো ছোট পথ, IRP (I/O অনুরোধ প্যাকেট। কার্নেল ড্রাইভারকে যে অনুরোধের পাত্র দেয়) না বানিয়ে ক্যাশের সঙ্গে সরাসরি ডেটা আদান-প্রদান করে। Procmon-এর Operation কলামে IRP_MJ_READ ও FASTIO_READ মিশে আসে কারণ একই «পড়া» সাধারণ পথ ও ছোট পথ দুই দিক দিয়ে যেতে পারে।
১ম কিস্তি ৫.২ অনুচ্ছেদে «সব I/O IRP হয় না» লিখেছি। উত্তর মিলানো।
ক্যাশে থাকা ফাইলের পড়া-লেখা IRP বানিয়ে ডিভাইস স্ট্যাক বইয়ে না দিয়ে ক্যাশের সঙ্গে মেমরি কপিতেই শেষ হয় জানা। তাই Windows ক্যাশ করা ফাইলে সিঙ্ক্রোনাস I/O-এর জন্য ফাস্ট I/O ছোট পথ রাখে — IRP না বানিয়ে ফাইল সিস্টেমের «ফাস্ট I/O এন্ট্রি পয়েন্ট» সরাসরি ডেকে ক্যাশ ম্যানেজার থেকে সরাসরি কপি।6 ফাস্ট I/O সামলাতে না পারলে (ক্যাশে নেই, লক জড়ায়, ফিল্টার মাঝে ঢোকে ইত্যাদি) সাধারণ IRP পথে ফেরে। এটা সিঙ্ক্রোনাস অনুরোধের দ্রুত পথ, «ক্যাশ হিট = সবসময় ফাস্ট I/O» নয়। অ্যাসিঙ্ক্রোনাস (FILE_FLAG_OVERLAPPED) হ্যান্ডেলের অপারেশন ক্যাশ থেকে সেখানেই শেষ হলেও (২য় কিস্তি ৫ অধ্যায়) IRP পথে সামলানো হতে পারে।
flowchart TB
REQ["ক্যাশ-চালু হ্যান্ডেলে সিঙ্ক্রোনাস পড়া-লেখা"]
Q{"ফাস্ট I/O-তে সামলানো যায় কি<br/>(ক্যাশে আছে ইত্যাদি)"}
FAST["ফাস্ট I/O<br/>IRP না বানিয়ে ক্যাশের সঙ্গে সরাসরি কপি<br/>Procmon-এ FASTIO_ দেখায়"]
IRP["সাধারণ পথ<br/>IRP বানিয়ে ডিভাইস স্ট্যাকে<br/>(১ম কিস্তির চিত্র ৬-এর জগৎ)"]
REQ --> Q
Q -->|যায়| FAST
Q -->|যায় না| IRP
চিত্র ৮: ফাস্ট I/O-এর শাখা। Procmon-এ FASTIO_READ ও IRP_MJ_READ মিশে দেখা যায় এজন্যই
১ম কিস্তি ৭ অধ্যায়-এর Procmon পর্যবেক্ষণে FASTIO_ সারি মিশে থাকার কারণ এখন ব্যাখ্যা যায়। ক্যাশ হিট পড়া IRP-ও বিলাস। এই পথের অস্তিত্ব ৬ষ্ঠ কিস্তির ফিল্টার ড্রাইভারেও প্রভাব ফেলে (মিনিফিল্টার ফাস্ট I/O-তেও ঢুকতে পারে)।
8. সারসংক্ষেপ
- Windows-এর ফাইল ক্যাশ রাইট-ব্যাক, সত্তা ফাইলের 256KB খণ্ডের ম্যাপিং। ক্যাশ-চালু পড়া-লেখা স্লটের সঙ্গে মেমরি কপি।1
- পড়ায় আগে পড়া অনুমান করে,
SequentialScan/RandomAccessতার ইঙ্গিত।1 - লেখা প্রতি সেকেন্ডের lazy writer পেছন থেকে করে। অ্যাপ মরলেও ডেটা থাকে, OS-সহ মরলে ডার্টি অংশই হারায়। নকশার প্রশ্ন «এই ডেটা পাওয়ার কাটের মুহূর্তে হারালে চলে কি»।1
- নিশ্চিত লেখার সরঞ্জাম
FlushFileBuffers(মোড়ে নিশ্চিত) /WRITE_THROUGH(প্রতি লেখায়) /NO_BUFFERING(ক্যাশ ছাড়া + সারিবদ্ধতার শর্ত)। প্রতিবার ফ্লাশ অদক্ষ, ঘন ঘন স্থায়িত্বে NO_BUFFERING+WRITE_THROUGH একসঙ্গে সরকারি সুপারিশ। মেটাডেটা সবসময় ক্যাশ হয় — এটাও খেয়াল।231 - ম্যাপ ভিউ ও ক্যাশ একই পেজ ভাগ করে সামঞ্জস্যপূর্ণ। বাইরে শুধু NO_BUFFERING। ম্যাপের স্থায়িত্ব
FlushViewOfFile+FlushFileBuffersদুই ধাপ।45 - ক্যাশ হিট সিঙ্ক্রোনাস পড়া-লেখা ফাস্ট I/O-তে IRP-ও বাদ দেয়। ১ম কিস্তির Procmon-এ দেখা
FASTIO_-এর আসল রূপ।6
পরেরটা ৫ম কিস্তি «NTFS-এর অভ্যন্তরীণ কাঠামো — MFT থেকে বোঝা ফাইল সিস্টেম»। এতদিন ফাইলকে «অফসেট ও বাইট সারি» হিসেবে দেখেছি, তার পেছনে NTFS ডেটা কীভাবে সাজায় — MFT, একাধিক ডেটা স্ট্রিম, জার্নাল, হার্ড লিঙ্ক — ডিস্কের উপরের স্থির কাঠামোয় নামব।
সম্পর্কিত নিবন্ধ
- Windows I/O-এর গভীরতা (১ম কিস্তি) — সব পড়া-লেখা IRP হয়: I/O সিস্টেমের পুরো চিত্র
- Windows I/O-এর গভীরতা (২য় কিস্তি) — সিঙ্ক্রোনাস I/O ও অ্যাসিঙ্ক্রোনাস I/O: OVERLAPPED-এর আসল অর্থ
- Windows I/O-এর গভীরতা (৩য় কিস্তি) — I/O Completion Port (IOCP) ও .NET থ্রেড পুল: async/await-এর তলাঘর
- ফাইল সহযোগিতার একচেটিয়া নিয়ন্ত্রণের মৌলিক জ্ঞান — ফাইল লক ও পরমাণু claim-এর সেরা চর্চা
- শেয়ারড মেমরির ফাঁদ ও বাস্তব সেরা চর্চা
- C#-এ SQLite ব্যবসায়িক অ্যাপে ব্যবহার — WAL মোড·একচেটিয়া নিয়ন্ত্রণ·ক্ষতি প্রতিরোধ·EF Core-এর সঙ্গে ভাগ
- Windows-এ প্রোগ্রামের সংস্করণভেদে গতি সঠিকভাবে তুলনা করার পদ্ধতি
- Windows অ্যাপে USB ডিভাইস সামলানো — ভার্চুয়াল COM·HID·WinUSB·নিজস্ব SDK বেছে নেওয়া
সম্পর্কিত পরামর্শ ক্ষেত্র
KomuraSoft LLC «সেভ করা ডেটা গেছে», «ফাইল লেখা ধীর / অতিরিক্ত দ্রুত সন্দেহ» ধরনের Windows ব্যবসায়িক অ্যাপের ফাইল I/O নকশা·তদন্ত সামলায়।
তথ্যসূত্র
-
Microsoft Learn, File Caching। Windows ডিফল্টে ফাইল ডেটা ক্যাশ করে, পড়া সিস্টেম ফাইল ক্যাশ থেকে হয়, লেখাও ক্যাশে হয় — রাইট-ব্যাক ক্যাশ; ক্যাশ ফাইল অবজেক্ট এককে সামলানো হয় ও ক্যাশ ম্যানেজারের নেতৃত্বে চলে; ডিস্কে লেখা দেরি করে ক্যাশে রাখার নীতি বিলম্বিত লেখা (lazy writing) নামে ডাকা; ফাইল পড়ার সময় 256KB খণ্ড সিস্টেম অ্যাড্রেস স্পেসের 256KB স্লটে পড়া হয়, ইউজার প্রসেস সেই স্লটের সঙ্গে ডেটা কপি করে; ক্যাশ ম্যানেজার প্রতি সেকেন্ডে lazy writer চালু করে সম্প্রতি ফ্লাশ হয়নি এমন পেজের ৮ ভাগের ১ ভাগ ডিস্ক লেখার কিউতে তোলে, দরকার হলে আরও বাড়ায়; অস্থায়ী ফাইল ফ্লাশ হয় না; পাওয়ার হারানোর মতো হঠাৎ সিস্টেম বিঘ্ন হলে না-লেখা ক্যাশ ডেটা হারায়; FILE_FLAG_NO_BUFFERING দিয়ে ক্যাশ নিষ্ক্রিয় করলেও ফাইল মেটাডেটা ক্যাশ হতে পারে; FILE_FLAG_WRITE_THROUGH-এ ডেটা ক্যাশেও লেখা হয় ও lazy writer-এর দেরি ছাড়া সঙ্গে সঙ্গে ডিস্কে লেখা হয়; ফাইল সিস্টেম মেটাডেটা সবসময় ক্যাশ হয় তাই মেটাডেটার স্থায়িত্বে ফ্লাশ বা FILE_FLAG_WRITE_THROUGH লাগে — এসব বিষয়ে। ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9 ↩10 ↩11 ↩12 ↩13 ↩14 ↩15 ↩16 ↩17 ↩18 ↩19
-
Microsoft Learn, FlushFileBuffers function। WriteFile সাধারণত ভিতরের বাফারে লেখে, OS নিয়মিত ডিস্কে লেখে; FlushFileBuffers নির্দিষ্ট ফাইলের সব বাফার তথ্য ডিভাইস পর্যন্ত লেখে; অনেক লেখায় প্রতিবার ডাকা অদক্ষ, ঘন ঘন লেখায় গুরুত্বপূর্ণ ডেটার স্থায়িত্ব লাগে এমন অ্যাপ FILE_FLAG_NO_BUFFERING ও FILE_FLAG_WRITE_THROUGH দিয়ে আনবাফারড I/O ব্যবহার করা উচিত; ভলিউম হ্যান্ডেলে ডাকলে (প্রশাসক অধিকারে) সেই ভলিউমের সব খোলা ফাইল ফ্লাশ যায় — এসব বিষয়ে। ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, File Buffering। FILE_FLAG_NO_BUFFERING দিয়ে খোলা ফাইলের অ্যাক্সেস শর্ত: পড়া-লেখার আকার ও ফাইল অফসেট (OVERLAPPED দিয়ে নির্দিষ্টসহ) ভলিউমের সেক্টর আকারের পূর্ণ গুণিতক হতে হবে; পড়া-লেখার বাফারের ঠিকানা ভৌত সেক্টর আকারে সারিবদ্ধ থাকা উচিত; ভৌত সেক্টর 4,096 বাইটের Advanced Format ডিভাইসের খেয়াল লাগে — এসব বিষয়ে। ↩ ↩2 ↩3 ↩4
-
Microsoft Learn, File Mapping। ফাইল ম্যাপিং অবজেক্ট ডিস্কের ফাইলে পিঠ দেয়, পেজ সোয়াপ-আউট বদলের ভিতর ফাইলে লেখা হিসেবে হয়; একাধিক প্রসেস একই ফাইল ম্যাপিং অবজেক্ট থেকে স্থানীয় ফাইলের ভিউ বানালে ডেটা সামঞ্জস্যপূর্ণ (ডিস্কের ফাইলের সঙ্গে একই ভিতর) — এসব বিষয়ে। ↩ ↩2 ↩3
-
Microsoft Learn, FlushViewOfFile function। FlushViewOfFile ম্যাপ ভিউয়ের পরিসরের ডার্টি পেজ ডিস্কে লেখা শুরু করে; এই ফাংশন ফাইল মেটাডেটা ফ্লাশ করে না, হার্ডওয়্যার ডিস্ক ক্যাশ থেকে ভৌত লেখা শেষও অপেক্ষা করে না; ডার্টি পেজ ও মেটাডেটা সব ভৌতভাবে লিখে শেষ করতে FlushViewOfFile-এর পর FlushFileBuffers ডাকা উচিত — এসব বিষয়ে। ↩ ↩2 ↩3
-
Microsoft Learn, IRPs Are Different From Fast I/O। ফাস্ট I/O IRP না বানিয়ে ফাইল সিস্টেম বা ক্যাশ ম্যানেজারের এন্ট্রি পয়েন্ট সরাসরি ডাকে, ক্যাশ করা ফাইলের সিঙ্ক্রোনাস I/O-এর দ্রুত পথ; ক্যাশ থেকে সরাসরি ইউজার বাফারে (বা উল্টো দিকে) ডেটা স্থানান্তর হয়; ফাস্ট I/O সামলাতে না পারলে IRP-ভিত্তিক সাধারণ পথ ব্যবহার হয় — এসব বিষয়ে। ↩ ↩2 ↩3
-
Microsoft Learn, Asynchronous disk I/O appears as synchronous on Windows। ডেটা ক্যাশে থাকলে অনুরোধ সেখানেই শেষ হয়ে TRUE ফেরে; Windows-এর ক্যাশ ফাইল ম্যাপিং দিয়ে বাস্তবায়িত, পেজ না থাকলে অ্যাসিঙ্ক্রোনাস পেজ ফল্ট ব্যবস্থা নেই, তাই ক্যাশ-চালু অ্যাসিঙ্ক্রোনাস পড়া সিঙ্ক্রোনাসে সামলানো হতে পারে — এসব বিষয়ে। ↩
-
Microsoft Learn, FileStream.Flush method (.NET)। Flush() স্ট্রিমের ভিতরের বাফার OS-এ লেখে; Flush(true) দিলে তার সঙ্গে সব মাঝের ফাইল বাফার (OS-এর বাফার)ও ফ্লাশ হয় — এসব বিষয়ে। ↩
সম্পর্কিত নিবন্ধ
কাছাকাছি বিষয়ে গভীরে যেতে একই ট্যাগযুক্ত সাম্প্রতিক নিবন্ধ।
Windows I/O-এর গভীরতা (৫ম কিস্তি) — NTFS-এর অভ্যন্তরীণ কাঠামো: MFT থেকে বোঝা ফাইল সিস্টেম
NTFS-এর অভ্যন্তরীণ কাঠামো চিত্রে ব্যাখ্যা করা ধারাবাহিকের ৫ম কিস্তি। MFT ও ফাইল রেকর্ড, একাধিক ডেটা স্ট্রিম (Zone.Identifier), হার্ড লিঙ্...
Windows I/O-এর গভীরতা (৬ষ্ঠ কিস্তি·শেষ) — ফিল্টার ড্রাইভার ও মিনিফিল্টার: Procmon ও ভাইরাস স্ক্যান I/O-তে কেন ঢুকতে পারে
Windows-এর ফিল্টার ড্রাইভার ও মিনিফিল্টার চিত্রে ব্যাখ্যা করা ধারাবাহিকের শেষ কিস্তি। ফিল্টার ম্যানেজার ও অ্যালটিটিউড, pre/post কলব্যাক, ...
ব্যবহারিক মাল্টিথ্রেডিং সেরা অনুশীলন: .NET সংস্করণ — আরও থ্রেড যোগ করার আগে কী ঠিক করবেন
.NET/C#-এ মাল্টিথ্রেডেড কোড যেন মাঝে মাঝে ক্র্যাশ বা হ্যাং না করে, তার ডিজাইন নিয়ম: নিজে থ্রেড না বানিয়ে Task-এ চড়া, ভাগ করা পরিবর্তনয...
C# ও PowerShell থেকে WMI/CIM ব্যবহার — হার্ডওয়্যার তথ্য, প্রক্রিয়া নজরদারি ও দূরবর্তী অনুসন্ধানের বাস্তব নির্দেশিকা
PC-র সিরিয়াল নম্বর, ডিস্কের খালি জায়গা ও প্রক্রিয়া চালু হওয়া শনাক্তের নিয়মিত উপায় WMI/CIM। Get-CimInstance-এর মতো CIM কমান্ডলেট, পু...
নেমড পাইপ ব্যবহারিকভাবে — ডিজাইন থেকে নিরাপত্তা পর্যন্ত Windows-এর মানক IPC
Windows-এর মানক আন্তঃপ্রক্রিয়া যোগাযোগ নেমড পাইপের ব্যবহারিক গাইড। প্রাথমিক উৎস থেকে এই নিবন্ধ বাইট ও মেসেজ মোডের পছন্দ, একাধিক ক্লায়েন...
সম্পর্কিত বিষয়
এই পৃষ্ঠাগুলো বিষয়টিকে সেবা ও সিদ্ধান্তের বৃহত্তর প্রেক্ষাপটে স্থাপন করে।
Windows-এর প্রযুক্তিগত বিষয়
Windows ডেভেলপমেন্ট, বাগ তদন্ত ও বিদ্যমান সম্পদ ব্যবহারের প্রবেশদ্বার।
এই বিষয়ের সাথে সম্পর্কিত সেবা
নিবন্ধটি নিচের সেবাগুলোর সাথে সরাসরি সম্পর্কিত।
Windows অ্যাপ ডেভেলপমেন্ট
ব্যবসায়িক অ্যাপ, ডিভাইস ইন্টিগ্রেশন ও যোগাযোগ টুল, চাহিদা থেকে ডেভেলপমেন্ট পর্যন্ত।
প্রায়শ জিজ্ঞাসিত প্রশ্ন
এই নিবন্ধের বিষয়ে পরামর্শে প্রায়ই আসা প্রশ্ন।
- WriteFile সফল ফেরালেই কি ডেটা ডিস্কে লেখা হয়ে গেছে?
- ডিফল্টে লেখা হয়নি। Windows-এর ফাইল ক্যাশ রাইট-ব্যাক পদ্ধতি, WriteFile ডেটা সিস্টেম ফাইল ক্যাশে কপি হওয়ার মুহূর্তেই সফল ফেরায়। ডিস্কে লেখা ক্যাশ ম্যানেজার প্রতি সেকেন্ডে চালু করা বিলম্বিত লেখা (lazy writer) পরে করে। জরুরি হল বিঘ্নের ধরন অনুযায়ী ফারাক। অ্যাপের প্রসেস ক্র্যাশ করলেও ক্যাশে যাওয়া ডেটা OS বেঁচে থাকলে পরে লেখা হয়, হারায় না। অন্যদিকে OS-সহ পড়ে যাওয়া বিঘ্ন (পাওয়ার কাট, ব্লু স্ক্রিন)-এ এখনও না লেখা ডার্টি ক্যাশ হারায়। «WriteFile সফল = স্থায়ী হয়েছে» নয়, «সফল = OS-এর হাতে তুলে দিয়েছে» বোঝাই সঠিক।
- নিশ্চিতভাবে ডিস্কে লিখতে কী করবেন?
- তিনটে সরঞ্জাম আছে। প্রথম FlushFileBuffers, সেই ফাইলের বাফার করা ডেটা ও মেটাডেটা ডিভাইস পর্যন্ত লিখে শেষ করে (.NET-এ FileStream.Flush(true) এর সমতুল্য)। দ্বিতীয় FILE_FLAG_WRITE_THROUGH, প্রতি লেখায় ক্যাশে লিখে সঙ্গে সঙ্গে ডিস্কেও লেখে। তৃতীয় FILE_FLAG_NO_BUFFERING, ক্যাশ নিজেই পেরোয় না। Microsoft-এর নথি বলে, প্রতি লেখায় FlushFileBuffers ডাকা অদক্ষ, ঘন ঘন লেখায় নিশ্চিত স্থায়িত্ব লাগলে FILE_FLAG_NO_BUFFERING ও FILE_FLAG_WRITE_THROUGH একসঙ্গে ব্যবহার করা উচিত। সবকটাই ক্যাশের সুবিধা ছেড়ে দেয় বলে ধীর হয়, তাই «সবকিছুতে লাগান» নয়, হারানো চলে না এমন ডেটার লেখায় সীমাবদ্ধ রাখাই বাস্তব কৌশল।
- FILE_FLAG_WRITE_THROUGH আর FILE_FLAG_NO_BUFFERING-এর ফারাক কী?
- WRITE_THROUGH «ক্যাশে লেখে, শেষ হওয়ার আগে ডিস্কেও লেখে»। পড়া এখনও ক্যাশের সুবিধা পায়, বিলম্বিত লেখার দেরিই শুধু সরানো হয়। NO_BUFFERING «পড়া-লেখা সিস্টেম ক্যাশ পেরোয় না», পড়াও লেখাও প্রতিবার ডিস্ক ডিভাইসে I/O হয় (তবে পেরোয় Windows-এর ক্যাশ পর্যন্ত, ডিভাইসের ভিতরের লেখার ক্যাশ নয়)। তার বদলে কঠোর বাধা থাকে। পড়া-লেখার আকার ও ফাইল অফসেট ভলিউমের সেক্টর আকারের পূর্ণ গুণিতক হতে হবে, বাফারের ঠিকানাও ভৌত সেক্টর সীমায় সারিবদ্ধ থাকতে হবে। আর NO_BUFFERING-এও ফাইল সিস্টেমের মেটাডেটা ক্যাশ হতেই থাকে, মেটাডেটা পর্যন্ত নিশ্চিত লিখতে FlushFileBuffers বা WRITE_THROUGH একসঙ্গে লাগে। ডেটাবেস ইঞ্জিনের মতো নিজে বাফার সামলানো সফটওয়্যারই সাধারণত ব্যবহার করে; সাধারণ অ্যাপে আগে WRITE_THROUGH বা FlushFileBuffers ভাবাই যুক্তিসঙ্গত।
- টাস্ক ম্যানেজারে খালি মেমরি কম দেখা গেলে ফাইল ক্যাশের দোষ?
- অনেক সময় তাই, আর এটা স্বাভাবিক আচরণ। Windows খালি ভৌত মেমরি সক্রিয়ভাবে ফাইল ক্যাশ হিসেবে ব্যবহার করে, বড় ফাইল কপি বা প্রচুর পড়া-লেখা করলে সেই পরিমাণে ক্যাশ ফুলে মেমরি ব্যবহার বেড়ে দেখায়। তবে ক্যাশ যে পেজ ব্যবহার করে তার অনেকগুলো অ্যাপ মেমরি চাইলে তুলনামূলক তাড়াতাড়ি অন্য কাজে দেওয়া যায়, «মেমরি খেয়ে শেষ হয়ে কম পড়েছে» অবস্থা থেকে আলাদা করে দেখা লাগে। মেমরি কম সন্দেহ হলে দেখা খালি পরিমাণই নয়, কমিটেড মেমরি বা হার্ড ফল্টের ঘনত্বের মতো সূচক দেখাই বাস্তব।
- মেমরি-ম্যাপড ফাইল আর ReadFile/WriteFile দিয়ে একই ফাইল ছুঁলে ভিতর কি আলাদা হয়ে যায়?
- সাধারণ ক্যাশ-চালু I/O-এর সঙ্গে যায় না। Windows-এর ক্যাশ নিজেই ফাইল ম্যাপিং দিয়ে বাস্তবায়িত, একই স্থানীয় ফাইলে ম্যাপ ভিউ ও ক্যাশ একই ডেটা ভাগ করে, একদিকের বদল অন্যদিক থেকেও দেখা যায়। একাধিক প্রসেস একই ফাইল ম্যাপিং অবজেক্ট থেকে ভিউ বানালেও ডেটা সামঞ্জস্যপূর্ণ (কোহেরেন্ট) থাকে। তবে FILE_FLAG_NO_BUFFERING দিয়ে খোলা হ্যান্ডেলের পড়া-লেখা ক্যাশ পেরোয় না, তাই এই সামঞ্জস্যের বাইরে। ম্যাপ ভিউয়ের বদল নিশ্চিত ডিস্কে লিখতে FlushViewOfFile একা মেটাডেটা লেখে না এবং হার্ডওয়্যার ক্যাশও অপেক্ষা করে না, তাই FlushViewOfFile-এর পর FlushFileBuffers ডাকতে হয়।