भीतर मैं एक स्मृति खंड जो MAP_ANONYMOUS
साथ mmap
के माध्यम से प्राप्त किया गया था।का आवंटन प्रति एक प्रक्रिया
मैं एक ही आकार के पहले एक का संदर्भ जिसमें से एक दूसरे स्मृति खंड कैसे आवंटित और दोनों कॉपी-ऑन लिखने लिनक्स में (कार्य लिनक्स 2.6.36 पल में) कर सकते हैं?
मैं सिर्फ एक नई प्रक्रिया बनाने के बिना fork
के रूप में एक ही प्रभाव वास्तव में करने के लिए, चाहते हैं। मैं चाहता हूं कि नया मानचित्रण एक ही प्रक्रिया में रहे।
पूरी प्रक्रिया को मूल और प्रतिलिपि पृष्ठों दोनों पर दोहराने योग्य होना चाहिए (जैसे कि माता-पिता और बच्चा fork
जारी रहेगा)।
कारण मैं पूरे सेगमेंट की सीधी प्रति आवंटित नहीं करना चाहता हूं क्योंकि वे कई गीगाबाइट बड़े हैं और मैं स्मृति का उपयोग नहीं करना चाहता जो कॉपी-ऑन-राइट साझा किया जा सकता है।
मैं क्या कोशिश की है:
mmap
खंड, साझा गुमनाम। डुप्लिकेशंस mprotect
पर इसे केवल पढ़ने के लिए और remap_file_pages
के साथ एक दूसरा मैपिंग भी केवल पढ़ने के लिए।
फिर लिखने के प्रयासों को रोकने के लिए libsigsegv
का उपयोग करें, मैन्युअल रूप से पृष्ठ की एक प्रति बनाएं और फिर mprotect
दोनों को पढ़ने-लिखने के लिए करें।
चाल है, लेकिन बहुत गंदा है। मैं अनिवार्य रूप से अपने स्वयं के वीएम को लागू कर रहा हूं।
दुख की बात mmap
आईएन /proc/self/mem
वर्तमान लिनक्स पर समर्थित नहीं है, अन्यथा MAP_PRIVATE
मानचित्रण चाल चल सकता है।
कॉपी-ऑन-राइट यांत्रिकी लिनक्स वी एम का हिस्सा हैं, वहाँ एक नई प्रक्रिया बनाने के बिना उनमें से उपयोग करने के लिए एक तरह से किया जाना है।
एक नोट के रूप में: मैं मच वी एम में उचित यांत्रिकी मिल गया है।
निम्नलिखित कोड मेरे ओएस एक्स 10.7.5 पर संकलित करता है तथा अपेक्षित व्यवहार है: Darwin 11.4.2 Darwin Kernel Version 11.4.2: Thu Aug 23 16:25:48 PDT 2012; root:xnu-1699.32.7~1/RELEASE_X86_64 x86_64 i386
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#ifdef __MACH__
#include <mach/mach.h>
#endif
int main() {
mach_port_t this_task = mach_task_self();
struct {
size_t rss;
size_t vms;
void * a1;
void * a2;
char p1;
char p2;
} results[3];
size_t length = sysconf(_SC_PAGE_SIZE);
vm_address_t first_address;
kern_return_t result = vm_allocate(this_task, &first_address, length, VM_FLAGS_ANYWHERE);
if (result != ERR_SUCCESS) {
fprintf(stderr, "Error allocating initial 0x%zu memory.\n", length);
return -1;
}
char * first_address_p = first_address;
char * mirror_address_p;
*first_address_p = 'a';
struct task_basic_info t_info;
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
task_info(this_task, TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
task_info(this_task, TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
results[0].rss = t_info.resident_size;
results[0].vms = t_info.virtual_size;
results[0].a1 = first_address_p;
results[0].p1 = *first_address_p;
vm_address_t mirrorAddress;
vm_prot_t cur_prot, max_prot;
result = vm_remap(this_task,
&mirrorAddress, // mirror target
length, // size of mirror
0, // auto alignment
1, // remap anywhere
this_task, // same task
first_address, // mirror source
1, // Copy
&cur_prot, // unused protection struct
&max_prot, // unused protection struct
VM_INHERIT_COPY);
if (result != ERR_SUCCESS) {
perror("vm_remap");
fprintf(stderr, "Error remapping pages.\n");
return -1;
}
mirror_address_p = mirrorAddress;
task_info(this_task, TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
results[1].rss = t_info.resident_size;
results[1].vms = t_info.virtual_size;
results[1].a1 = first_address_p;
results[1].p1 = *first_address_p;
results[1].a2 = mirror_address_p;
results[1].p2 = *mirror_address_p;
*mirror_address_p = 'b';
task_info(this_task, TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count);
results[2].rss = t_info.resident_size;
results[2].vms = t_info.virtual_size;
results[2].a1 = first_address_p;
results[2].p1 = *first_address_p;
results[2].a2 = mirror_address_p;
results[2].p2 = *mirror_address_p;
printf("Allocated one page of memory and wrote to it.\n");
printf("*%p = '%c'\nRSS: %zu\tVMS: %zu\n",results[0].a1, results[0].p1, results[0].rss, results[0].vms);
printf("Cloned that page copy-on-write.\n");
printf("*%p = '%c'\n*%p = '%c'\nRSS: %zu\tVMS: %zu\n",results[1].a1, results[1].p1,results[1].a2, results[1].p2, results[1].rss, results[1].vms);
printf("Wrote to the new cloned page.\n");
printf("*%p = '%c'\n*%p = '%c'\nRSS: %zu\tVMS: %zu\n",results[2].a1, results[2].p1,results[2].a2, results[2].p2, results[2].rss, results[2].vms);
return 0;
}
मैं लिनक्स में एक ही प्रभाव चाहते हैं।
आप btrfs का उपयोग कर सकते हैं और कॉपी-ऑन-राइट फीचर के साथ अपनी फ़ाइल डुप्लिकेशन का उपयोग कर सकते हैं ... हालांकि, आपके पास एफएस में आपके डेटा की अनावश्यक प्रतियां होंगी। काम करना चाहिए, लेकिन बिल्कुल उच्च प्रदर्शन नहीं। – thejh
कर्नेल को प्रश्न से बाहर खींच रहा है? – thejh
@thejh दुर्भाग्य से यह :(है। कोड पर। एक और फाइल सिस्टम नियोजित करना एक विकल्प या तो एक ही कारण के लिए और performance.'/dev/shm' (नहीं है मशीनों पर परिनियोजन योग्य मैं जड़ नहीं है होना है tmpfs) वास्तव में किस प्रकार की जाती है प्रति-ऑन-राइट ग्राहक कोड, जब दोनों प्रतियों की ग्राहकों को एक ही पता स्थान साझा करने के लिए देखने के लिए चाहिए के रूप में मैं फ़ाइल समर्थित स्मृति के साथ जाने के लिए तैयार हूँ के रूप में दूर है। –