तो मैं मॉड्यूल एक अलग कोर में मार डाला प्राप्त करना चाहते हैं।
और
वास्तव में हमारी प्रणाली में एक विशिष्ट कोर को अलग करने और उस कोर
यह एक काम स्रोत संकलित और एक डेबियन बॉक्स पर परीक्षण कोड है सिर्फ एक विशिष्ट प्रक्रिया निष्पादित कर्नेल 3.16 का उपयोग कर। मैं वर्णन करूंगा कि पहले लोड और अनलोड कैसे करें और पैरामीटर पारित करने का अर्थ क्या है।
सभी स्रोतों GitHub यहां पाया जा सकता है ...
https://github.com/harryjackson/doc/tree/master/linux/kernel/toy/toy
बिल्ड और मॉड्यूल लोड ...
make
insmod toy param_cpu_id=2
मॉड्यूल उपयोग
rmmod toy
उतारना करने के लिए
मैं modprobe का उपयोग नहीं कर रहा हूं क्योंकि यह कुछ विन्यास आदि की अपेक्षा करता है।पैरामीटर जिसे हम toy
कर्नेल मॉड्यूल में पास कर रहे हैं वह सीपीयू है जिसे हम अलग करना चाहते हैं। कॉल किए जाने वाले डिवाइस ऑपरेशंस में से कोई भी तब तक चलाएगा जब तक कि वह उस CPU पर निष्पादित नहीं हो जाता।
एक बार मॉड्यूल लोड किया जाता है आप की तरह
cat /dev/toy
यहाँ
/dev/toy
सरल संचालन इसे पा सकते हैं कि घटनाओं कर्नेल मॉड्यूल कैच और कुछ उत्पादन का उत्पादन पैदा करते हैं। आप dmesg
का उपयोग कर आउटपुट देख सकते हैं।
स्रोत कोड ...
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harry");
MODULE_DESCRIPTION("toy kernel module");
MODULE_VERSION("0.1");
#define DEVICE_NAME "toy"
#define CLASS_NAME "toy"
static int param_cpu_id;
module_param(param_cpu_id , int, (S_IRUSR | S_IRGRP | S_IROTH));
MODULE_PARM_DESC(param_cpu_id, "CPU ID that operations run on");
//static void bar(void *arg);
//static void foo(void *cpu);
static int toy_open( struct inode *inodep, struct file *fp);
static ssize_t toy_read( struct file *fp , char *buffer, size_t len, loff_t * offset);
static ssize_t toy_write( struct file *fp , const char *buffer, size_t len, loff_t *);
static int toy_release(struct inode *inodep, struct file *fp);
static struct file_operations toy_fops = {
.owner = THIS_MODULE,
.open = toy_open,
.read = toy_read,
.write = toy_write,
.release = toy_release,
};
static struct miscdevice toy_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "toy",
.fops = &toy_fops
};
//static int CPU_IDS[64] = {0};
static int toy_open(struct inode *inodep, struct file *filep) {
int this_cpu = get_cpu();
printk(KERN_INFO "open: called on CPU:%d\n", this_cpu);
if(this_cpu == param_cpu_id) {
printk(KERN_INFO "open: is on requested CPU: %d\n", smp_processor_id());
}
else {
printk(KERN_INFO "open: not on requested CPU:%d\n", smp_processor_id());
}
put_cpu();
return 0;
}
static ssize_t toy_read(struct file *filep, char *buffer, size_t len, loff_t *offset){
int this_cpu = get_cpu();
printk(KERN_INFO "read: called on CPU:%d\n", this_cpu);
if(this_cpu == param_cpu_id) {
printk(KERN_INFO "read: is on requested CPU: %d\n", smp_processor_id());
}
else {
printk(KERN_INFO "read: not on requested CPU:%d\n", smp_processor_id());
}
put_cpu();
return 0;
}
static ssize_t toy_write(struct file *filep, const char *buffer, size_t len, loff_t *offset){
int this_cpu = get_cpu();
printk(KERN_INFO "write called on CPU:%d\n", this_cpu);
if(this_cpu == param_cpu_id) {
printk(KERN_INFO "write: is on requested CPU: %d\n", smp_processor_id());
}
else {
printk(KERN_INFO "write: not on requested CPU:%d\n", smp_processor_id());
}
put_cpu();
return 0;
}
static int toy_release(struct inode *inodep, struct file *filep){
int this_cpu = get_cpu();
printk(KERN_INFO "release called on CPU:%d\n", this_cpu);
if(this_cpu == param_cpu_id) {
printk(KERN_INFO "release: is on requested CPU: %d\n", smp_processor_id());
}
else {
printk(KERN_INFO "release: not on requested CPU:%d\n", smp_processor_id());
}
put_cpu();
return 0;
}
static int __init toy_init(void) {
int cpu_id;
if(param_cpu_id < 0 || param_cpu_id > 4) {
printk(KERN_INFO "toy: unable to load module without cpu parameter\n");
return -1;
}
printk(KERN_INFO "toy: loading to device driver, param_cpu_id: %d\n", param_cpu_id);
//preempt_disable(); // See notes below
cpu_id = get_cpu();
printk(KERN_INFO "toy init called and running on CPU: %d\n", cpu_id);
misc_register(&toy_device);
//preempt_enable(); // See notes below
put_cpu();
//smp_call_function_single(1,foo,(void *)(uintptr_t) 1,1);
return 0;
}
static void __exit toy_exit(void) {
misc_deregister(&toy_device);
printk(KERN_INFO "toy exit called\n");
}
module_init(toy_init);
module_exit(toy_exit);
कोड ऊपर दो तरीकों आप सीपीयू की यानी अलगाव के लिए और एक अलग कोर पर init
रन पर पूछा होता है।
इनिट get_cpu
पर प्रीमेप्शन अक्षम करता है यानी इसके बाद आने वाली किसी भी चीज़ को कर्नेल द्वारा पूर्ववत नहीं किया जाएगा और एक कोर पर चलाया जाएगा। ध्यान दें, यह 3.16 का उपयोग कर गिरी किया गया था, अपने लाभ के लिए अपने कर्नेल संस्करण के आधार पर भिन्न हो सकते हैं, लेकिन मुझे लगता है कि इन एपीआई एक लंबे समय
यह Makefile है चारों ओर कर दिया गया है ...
obj-m += toy.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
नोट्स। get_cpu
में linux/smp.h
रूप
#define get_cpu() ({ preempt_disable(); smp_processor_id(); })
#define put_cpu() preempt_enable()
ताकि आप वास्तव में get_cpu
कॉल करने से पहले preempt_disable
कॉल करने के लिए की जरूरत नहीं है की घोषणा की है। get_cpu कॉल
preempt_count_inc();
barrier();
कॉल की निम्न क्रम के चारों ओर एक आवरण है ... और put_cpu वास्तव में इस कर रहा है ...
barrier();
if (unlikely(preempt_count_dec_and_test())) {
__preempt_schedule();
}
आप उपरोक्त का उपयोग कर की तरह आप के रूप में के रूप में कल्पना प्राप्त कर सकते हैं । लगभग सभी इस बात का के लिए ... रॉबर्ट प्यार से smp_call_function_single
लिनक्स कर्नेल विकास, पुस्तक निम्नलिखित स्रोतों से लिया गया था ..
गूगल।
http://derekmolloy.ie/writing-a-linux-kernel-module-part-2-a-character-device/
https://github.com/vsinitsyn/reverse/blob/master/reverse.c
विशिष्ट कोर के लिए बाँध विशिष्ट कर्नेल धागा के लिए, आप उपयोग कर सकते हैं [kthread_bind] (http://lxr.free-electrons.com/source/kernel/kthread.c#L366) या [set_cpu_allowed_ptr] (http://lxr.free-electrons.com/source/kernel/sched/core.c#L1262)। विशिष्ट कोर का उपयोग करने के लिए अन्य प्रक्रियाओं को अस्वीकार करने के लिए, आपको किसी भी तरह शेड्यूल कॉन्फ़िगर करने की आवश्यकता है। उदा।, जैसा कि वर्णन किया गया है [यहां] (http://unix.stackexchange.com/questions/186338/setting-system-wide-cpu-affinities-for-running-processes-on-a-linux-platform)। – Tsyvarev
@ Tsyvarev की टिप्पणी में जोड़ने के लिए: 'isolcpus' (कर्नेल पैरामीटर - दस्तावेज़ीकरण/कर्नेल-पैरामीटर.txt देखें) "सामान्य एसएमपी संतुलन और शेड्यूलिंग एल्गोरिदम से अलग करने के लिए एक या अधिक CPU निर्दिष्ट करने के लिए उपयोग किया जा सकता है। आप एक स्थानांतरित कर सकते हैं सीपीयू एफ़िनिटी सिस्कोल या सीपीयूसेट के माध्यम से "पृथक" सीपीयू को चालू या बंद करें। " –
@Tsyvarev और @Gil Hamlton। आपके उत्तरों के लिए धन्यवाद। मुझे 'kthread_bind' के बारे में पता है। प्रस्तावित समाधानों के बारे में: 'isolcpus' और' maxcpus', मेरी समझ से उन पैरामीटर को बूट करने के दौरान उपयोग किया जाना चाहिए। मैं पुनरारंभ किए बिना अलग करना चाहता हूं, वास्तव में, अलगाव केवल तब होता है जब मॉड्यूल लोड हो जाता है, इसलिए मुझे लगता है कि यह जाने का तरीका नहीं है। – insumity