/proc/$pid/maps
/proc/$pid/mem
id পিডের মেমরির বিষয়বস্তু প্রক্রিয়াটির মতোই ম্যাপযুক্ত দেখায়, অর্থাৎ সিউডো-ফাইলে অফসেট এক্স -এ বাইট প্রসেসের অ্যাড্রেস x এর বাইটের সমান । যদি কোনও প্রক্রিয়াটিতে কোনও ঠিকানা আনম্যাপ করা না থাকে তবে ফাইলটি সম্পর্কিত অফসেট থেকে পাঠানো EIO
(ইনপুট / আউটপুট ত্রুটি)। উদাহরণস্বরূপ, যেহেতু কোনও প্রক্রিয়ার প্রথম পৃষ্ঠাটি কখনই ম্যাপ করা হয় না (যাতে কোনও NULL
পয়েন্টারকে অবজ্ঞা করা প্রকৃত স্মৃতিতে অজ্ঞাতীতভাবে অ্যাক্সেস করার চেয়ে পরিষ্কারভাবে ব্যর্থ হয়), তাই /proc/$pid/mem
সর্বদা প্রথম বাইট পড়ার সাথে I / O ত্রুটি পাওয়া যায়।
প্রক্রিয়া মেমরির কোন অংশ ম্যাপ করা হয়েছে তা জানার উপায়টি হ'ল /proc/$pid/maps
। এই ফাইলটিতে ম্যাপ করা অঞ্চলে প্রতি লাইন রয়েছে, এটির মতো দেখতে:
08048000-08054000 r-xp 00000000 08:01 828061 /bin/cat
08c9b000-08cbc000 rw-p 00000000 00:00 0 [heap]
প্রথম দুটি সংখ্যা হ'ল অঞ্চলের সীমানা (প্রথম বাইটের ঠিকানা এবং শেষের পরে বাইট, হেক্সায়)। পরবর্তী কলামে অনুমতিগুলি অন্তর্ভুক্ত রয়েছে, তারপরে যদি ফাইলটি ম্যাপিং হয় তবে ফাইল সম্পর্কে কিছু তথ্য রয়েছে (অফসেট, ডিভাইস, ইনোড এবং নাম)। আরও তথ্যের জন্য proc(5)
ম্যান পৃষ্ঠা বা বোধগম্য লিনাক্স / প্রোক / আইডি / মানচিত্রগুলি দেখুন।
এখানে একটি প্রুফ-অফ কনসেপ্ট স্ক্রিপ্ট রয়েছে যা তার নিজস্ব স্মৃতিতে থাকা সামগ্রীকে ফেলে দেয়।
#! /usr/bin/env python
import re
maps_file = open("/proc/self/maps", 'r')
mem_file = open("/proc/self/mem", 'r', 0)
for line in maps_file.readlines(): # for each mapped region
m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
if m.group(3) == 'r': # if this is a readable region
start = int(m.group(1), 16)
end = int(m.group(2), 16)
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region contents
print chunk, # dump contents to standard output
maps_file.close()
mem_file.close()
/proc/$pid/mem
আপনি যদি mem
অন্য কোনও প্রক্রিয়ার সিউডো-ফাইল থেকে পড়ার চেষ্টা করেন তবে এটি কার্যকর হয় না: আপনি একটি ESRCH
(এরকম কোনও প্রক্রিয়া নয়) ত্রুটি পান।
/proc/$pid/mem
( r--------
) এর অনুমতিগুলি কী হওয়া উচিত তার চেয়ে বেশি উদার। উদাহরণস্বরূপ, আপনি কোনও সেটুইড প্রক্রিয়াটির স্মৃতি পড়তে সক্ষম হবেন না। তদ্ব্যতীত, প্রক্রিয়াটির মেমোরিটি পড়ার সময় কোনও প্রক্রিয়ার স্মৃতি পড়ার চেষ্টা করা পাঠককে মেমরির একটি বেমানান দৃষ্টিভঙ্গি দিতে পারে এবং আরও খারাপ এটি ছিল যে জাতিগুলির শর্ত ছিল যে লিনাক্স কার্নেলের পুরানো সংস্করণগুলি সনাক্ত করতে পারে ( যদিও এই lkml থ্রেড অনুসারে , আমি বিশদটি জানেন না)। সুতরাং অতিরিক্ত চেক প্রয়োজন:
- যে প্রক্রিয়াটি থেকে পড়তে চায় তা
/proc/$pid/mem
অবশ্যই পতাকাটির সাহায্যে প্রক্রিয়াটির ptrace
সাথে সংযুক্ত করতে হবে PTRACE_ATTACH
। ডিবাগাররা যখন কোনও প্রক্রিয়া ডিবাগ করা শুরু করেন এটিই; এটি strace
একটি প্রক্রিয়া সিস্টেম কল করতে কি। পাঠক একবার থেকে পড়া শেষ করার পরে, পতাকাটির সাথে /proc/$pid/mem
ডাক ptrace
দিয়ে এটি পৃথক করা উচিত PTRACE_DETACH
।
- পর্যবেক্ষণ প্রক্রিয়া চলমান হবে না। সাধারণত কলিং
ptrace(PTRACE_ATTACH, …)
লক্ষ্য প্রক্রিয়া বন্ধ করে দেয় (এটি একটি STOP
সংকেত প্রেরণ করে ), তবে একটি রেসের শর্ত রয়েছে (সিগন্যাল বিতরণটি অ্যাসিনক্রোনাস হয়), সুতরাং ট্রেসারকে কল করা উচিত wait
(ডকুমেন্টেড হিসাবে ptrace(2)
)।
রুট হিসাবে চলমান একটি প্রক্রিয়া কল করার প্রয়োজন ছাড়াই কোনও প্রক্রিয়ার স্মৃতি পড়তে পারে ptrace
, তবে পর্যবেক্ষণ প্রক্রিয়াটি অবশ্যই বন্ধ করা উচিত, বা পড়ার পরেও ফিরে আসবে ESRCH
।
লিনাক্স কার্নেল উত্সে, প্রতি-প্রক্রিয়াতে প্রবেশের কোড সরবরাহ /proc
করা রয়েছে fs/proc/base.c
এবং সেগুলি পড়তে /proc/$pid/mem
হবে mem_read
। অতিরিক্ত চেক দ্বারা সম্পাদিত হয় check_mem_permission
।
কোনও প্রক্রিয়াতে সংযুক্ত করার জন্য এবং এর mem
ফাইলটির একটি অংশ পড়ার জন্য এখানে কিছু নমুনা সি কোড দেওয়া হয়েছে (বাদ দেওয়াতে ত্রুটি):
sprintf(mem_file_name, "/proc/%d/mem", pid);
mem_fd = open(mem_file_name, O_RDONLY);
ptrace(PTRACE_ATTACH, pid, NULL, NULL);
waitpid(pid, NULL, 0);
lseek(mem_fd, offset, SEEK_SET);
read(mem_fd, buf, _SC_PAGE_SIZE);
ptrace(PTRACE_DETACH, pid, NULL, NULL);
আমি /proc/$pid/mem
অন্য থ্রেডে ডাম্প করার জন্য ইতিমধ্যে একটি প্রুফ-অফ-কনসেপ্ট স্ক্রিপ্ট পোস্ট করেছি ।