मैं प्रक्रिया के सिस्कोल का पता लगाने के लिए ptrace
का उपयोग कर रहा हूं। प्रक्रिया को फोर्क करने के बाद, मैं प्रक्रिया का पता लगाने के लिए PTRACE_TRACEME
का उपयोग करता हूं। कोड इस तरह दिखता है:किसी प्रक्रिया के सभी ट्रेसिंग सिस्कोल्स और सभी फोर्कड प्रक्रिया
while (true) {
int status;
int gotPid;
gotPid = waitpid(pid, &status, 0);
if (WIFEXITED(status) || WIFSIGNALED(status)) {
break;
}
if (WIFSTOPPED(status)) {
handleTrace();
}
}
तो फिर वहाँ है handleTrace
समारोह है, जो इस तरह दिखता है।
long syscall;
syscall = ptrace(PTRACE_PEEKUSER,
pid, 8 * ORIG_RAX, NULL);
// do something with the syscall
// continue program
ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
यह सब अच्छा है, लेकिन प्रक्रियाओं का पता लगाया प्रक्रिया (और यह भी प्रक्रिया द्वारा बनाई धागे) बनाता है, तो कार्यक्रम कांटे (या एक नया धागा बनाता है) मैं भी बच्चे को पता लगाने के लिए चाहते हैं। मुझे पता है कि यह PTRACE_O_TRACEFORK
, PTRACE_O_TRACEVFORK
और PTRACE_O_TRACECLONE
का उपयोग करके किया जा सकता है, लेकिन man
दस्तावेज से, यह पता लगाना बहुत मुश्किल है कि यह वास्तव में कैसे किया जाता है। मुझे इस पर कुछ उदाहरण चाहिए।
संपादित करें:
मैं एक ऐसी ही सवाल मिली: How to ptrace a multi-threaded application? मैं निम्नलिखित कोड के साथ की कोशिश की। यह कोड प्रारंभ प्रक्रिया की सिस्टम कॉल को ट्रैक करता है और यह भी फोर्क प्रक्रियाओं को ट्रैक करना है। यह माता-पिता प्रक्रिया में fork()
के बाद चलाया जाता है (बच्चा PTRACE_TRACEME
और exec()
पर कॉल करता है)।
EDIT2:
मैं कुछ और संशोधनों कोड पर, कुछ और प्रगति के साथ बनाया है।
long orig_eax;
int status;
int numPrograms = 1;
while(1) {
int pid;
CHECK_ERROR_VALUE(pid = waitpid(-1, &status, __WALL));
std::cout << pid << ": Got event." << std::endl;
if(WIFEXITED(status) || WIFSIGNALED(status)) {
std::cout << pid << ": Program exited." << std::endl;
if (--numPrograms == 0) {
break;
}
continue;
}
if (status >> 16 == PTRACE_EVENT_FORK || status >> 16 == PTRACE_EVENT_VFORK ||
status >> 16 == PTRACE_EVENT_CLONE) {
int newpid;
CHECK_ERROR_VALUE(ptrace(PTRACE_GETEVENTMSG, child, NULL, (long) &newpid));
std::cout << pid << ": Attached to offspring " << newpid << std::endl;
boost::this_thread::sleep(boost::posix_time::millisec(100));
CHECK_ERROR_VALUE(ptrace(PTRACE_SETOPTIONS,
newpid, NULL, PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE));
CHECK_ERROR_VALUE(ptrace(PTRACE_SYSCALL, newpid, NULL, NULL));
++numPrograms;
} else {
CHECK_ERROR_VALUE(ptrace(PTRACE_SETOPTIONS,
pid, NULL, PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE));
CHECK_ERROR_VALUE(orig_eax = ptrace(PTRACE_PEEKUSER,
pid, 8 * ORIG_RAX, NULL));
std::cout << pid << ": Syscall called: " <<
SyscallMap::instance().get().right.at(orig_eax) <<
std::endl;
CHECK_ERROR_VALUE(ptrace(PTRACE_SYSCALL,
pid, NULL, NULL));
}
}
CHECK_ERROR_VALUE
सिर्फ एक मैक्रो परिणाम कोड की जाँच करता है और उस में errno
के विवरण के साथ एक अपवाद फेंक है।
जाहिर है, जब मुझे एक कांटा/क्लोन की घटना मिलती है तो नई प्रक्रिया अभी तक मौजूद नहीं है, और मुझे एक "प्रक्रिया मौजूद नहीं है" त्रुटि संदेश मिलता है यदि मैं इसे पट्रेस करने का प्रयास करता हूं। अगर मैं नई प्रक्रिया को छेड़छाड़ करने की कोशिश करने से पहले नींद डालता हूं, तो मुझे एक त्रुटि संदेश नहीं मिलता है। अब जब कार्यक्रम कांटा/क्लोन के बिंदु पर जाता है, तो यह नई प्रक्रिया का पता लगाना शुरू कर देता है, लेकिन यह माता-पिता प्रक्रिया में clone()
सिस्कल के रिटर्न पॉइंट तक कभी नहीं पहुंचता है, जिसका अर्थ है कि बच्चा सफलतापूर्वक खत्म हो जाता है, लेकिन माता-पिता लटकता है अपने कांटा बिंदु पर।