2013-05-03 7 views
6

मैं एक कर्नेल ड्राइवर और एक उपयोगकर्ता के अंतरिक्ष कार्यक्रम (मुझे पता है कि सवाल है कि यहाँ इसी तरह की जानकारी के लिए पूछने के बहुत सारे हैं, लेकिन मैं कोई भी है कि sysfs_notify के साथ सौदा मिल सकता है) के बीच अतुल्यकालिक रूप से संवाद करने के लिए कोशिश कर रहा हूँ।लिनक्स का उपयोग करना sysfs_notify फोन

मैं विल्हेल्म के संपादन को यहां छोड़ रहा हूं, लेकिन इसे सरल बनाने के लिए एक सरल चालक दोनों को स्रोत जोड़ रहा हूं और इसे यूजर स्पेस प्रोग्राम को मतदान के लिए जोड़ रहा हूं। चालक ठीक काम करता है (मुझे नेट से अधिकतर मिला है; इसमें क्रेडिट गुम है, लेकिन जब मैं उन्हें जोड़ने के लिए वापस गया तो मैं उन्हें नहीं ढूंढ पाया)। दुर्भाग्य से, मतदान कार्यक्रम काम नहीं करता है। यह हमेशा सफलता देता है। दिलचस्प बात यह है कि अगर मैं चुनाव से पहले दो पढ़ नहीं करता हूं, तो विद्रोह करने वाले सदस्यों को पोलरर पर सेट किया जाता है। कार्यक्रम आउटपुट में देखा गया है कि सिर्फ पॉलीन की बजाय पॉलिन।

कार्यक्रम उत्पादन:

जड़ @ ubuntu:/घर/wmulcahy/डेमो # ./readhello
शुरू हो रहा
गुण फ़ाइल मूल्य: 74 (टी) [0]
revents [0]: 00000001
revents [1]: 00000001

यहाँ ड्राइवर है: hello.c (आप देख सकते हैं, जहां मैं बाहर शुरू कर दिया ...)

#include <linux/module.h> 
#include <linux/kernel.h> 
#include <linux/init.h> 
#include <linux/fs.h> 
#include <linux/slab.h> 

struct my_attr { 
    struct attribute attr; 
    int value; 
}; 

static struct my_attr notify = { 
    .attr.name="notify", 
    .attr.mode = 0644, 
    .value = 0, 
}; 

static struct my_attr trigger = { 
    .attr.name="trigger", 
    .attr.mode = 0644, 
    .value = 0, 
}; 

static struct attribute * myattr[] = { 
    &notify.attr, 
    &trigger.attr, 
    NULL 
}; 

static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) 
{ 
    struct my_attr *a = container_of(attr, struct my_attr, attr); 
    printk("hello: show called (%s)\n", a->attr.name); 
    return scnprintf(buf, PAGE_SIZE, "%s: %d\n", a->attr.name, a->value); 
} 
static struct kobject *mykobj; 

static ssize_t store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t len) 
{ 
    struct my_attr *a = container_of(attr, struct my_attr, attr); 

    sscanf(buf, "%d", &a->value); 
    notify.value = a->value; 
    printk("sysfs_notify store %s = %d\n", a->attr.name, a->value); 
    sysfs_notify(mykobj, NULL, "notify"); 
    return sizeof(int); 
} 

static struct sysfs_ops myops = { 
    .show = show, 
    .store = store, 
}; 

static struct kobj_type mytype = { 
    .sysfs_ops = &myops, 
    .default_attrs = myattr, 
}; 

static struct kobject *mykobj; 
static int __init hello_module_init(void) 
{ 
    int err = -1; 
    printk("Hello: init\n"); 
    mykobj = kzalloc(sizeof(*mykobj), GFP_KERNEL); 
    if (mykobj) { 
     kobject_init(mykobj, &mytype); 
     if (kobject_add(mykobj, NULL, "%s", "hello")) { 
      err = -1; 
      printk("Hello: kobject_add() failed\n"); 
      kobject_put(mykobj); 
      mykobj = NULL; 
     } 
     err = 0; 
    } 
    return err; 
} 

static void __exit hello_module_exit(void) 
{ 
    if (mykobj) { 
     kobject_put(mykobj); 
     kfree(mykobj); 
    } 
    printk("Hello: exit\n"); 
} 

module_init(hello_module_init); 
module_exit(hello_module_exit); 
MODULE_LICENSE("GPL"); 

और यहाँ चुनाव कार्यक्रम है: readhello.c

#include <stdint.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <poll.h> 

#define TEST_SYSFS_TRIGGER "/sys/hello/trigger" 
#define TEST_SYSFS_NOTIFY "/sys/hello/notify" 

int main(int argc, char **argv) 
{ 
    int cnt, notifyFd, triggerFd, rv; 
    char attrData[100]; 
    struct pollfd ufds[2]; 

    // Open a connection to the attribute file. 
    if ((notifyFd = open(TEST_SYSFS_NOTIFY, O_RDWR)) < 0) 
    { 
     perror("Unable to open notify"); 
     exit(1); 
    } 
    // Open a connection to the attribute file. 
    if ((triggerFd = open(TEST_SYSFS_TRIGGER, O_RDWR)) < 0) 
    { 
     perror("Unable to open trigger"); 
     exit(1); 
    } 

    ufds[0].fd = notifyFd; 
    ufds[0].events = POLLIN; 
    ufds[1].fd = triggerFd; 
    ufds[1].events = POLLIN; 

    // Someone suggested dummy reads before the poll() call 
    cnt = read(notifyFd, attrData, 100); 
    cnt = read(triggerFd, attrData, 100); 
    ufds[0].revents = 0; 
    ufds[1].revents = 0; 
    if ((rv = poll(ufds, 2, 10000)) < 0) 
    { 
     perror("poll error"); 
    } 
    else if (rv == 0) 
    { 
     printf("Timeout occurred!\n"); 
    } 
    else if (ufds[0].revents & POLLIN) 
    { 
     printf("triggered\n"); 
     cnt = read(notifyFd, attrData, 1); 
     printf("Attribute file value: %02X (%c) [%d]\n", attrData[0], attrData[0], cnt); 
    } 
    printf("revents[0]: %08X\n", ufds[0].revents); 
    printf("revents[1]: %08X\n", ufds[1].revents); 

    close(triggerFd); 
    close(notifyFd); 
} 

Some upcoming sysfs enhancements

आंतरिक रूप से, पैच सिस्टम पर प्रत्येक कोबजेक्ट में एक प्रतीक्षा कतार सिर जोड़ता है; कि कतार एक चुनाव() कॉल के जवाब में एक जनमत सर्वेक्षण तालिका में डाला जाता है। sysfs कोड जानने, तथापि, जब किसी भी sysfs की अधिक महत्व देते हैं बदल गया है का कोई रास्ता नहीं है, तो सबसिस्टम एक pollable विशेषता को लागू करने के लिए स्पष्ट कॉल करने चाहिए:, ली

void sysfs_notify(struct kobject *kobj, char *dir, char *attr); 

धन्यवाद

उत्तर

7

अवरोधन मतदान उपयोगकर्ता पक्ष से है। उपयोगकर्ता कोड केवल उस कर्नेल को बता सकता है जिसमें इसकी रूचि है, फिर poll() में अवरुद्ध करें जब तक कि उनमें से कोई भी बदल नहीं जाता है।

sysfs_notify() एक कर्नेल-साइड कॉल है जो उपयोगकर्ता-स्थान poll() जारी करता है। के बाद आप अपने कर्नेल विशेषता मान को समायोजित, बस sysfs_notify() फोन किसी भी उपयोगकर्ता के अंतरिक्ष अनुप्रयोग उनके उत्कृष्ट poll() पर प्रतिक्रिया के लिए अनुमति देने के लिए।

poll() के बारे में सोचें कि ब्याज की विशेषता में बदलाव की सूचनाओं के लिए "सदस्यता लेना" और sysfs_notify() किसी भी ग्राहक को "प्रकाशन" के रूप में "प्रकाशन" के रूप में सोचें।

+0

'स्वचालित रूप से sysfs गुण के लिए बुलाया sysfs_poll' नहीं है? –

+0

हां, उपयोगकर्ता-स्थान सर्वेक्षण() VFS के माध्यम से और अंत में sysfs_poll() से जुड़ता है। वह पक्ष है जो परिवर्तन की प्रतीक्षा कर रहा है। परिवर्तन जो उत्पन्न करता है वह सक्रिय sysfs_poll() को जागृत करने के लिए sysfs_notify() को कॉल करता है। – Peter

+0

आपके संपादन और उत्तर दोनों के लिए धन्यवाद।मैंने पहले ही उस संदर्भ को देखा था, विल्हेल्म, और समझ गया कि आप क्या कह रहे हैं, पीटर। मैं अपना ध्यान बदलने के लिए सवाल संपादित करने जा रहा हूं। मेरे पास इंटरनेट से खींचे गए कुछ कोड उदाहरण हैं और मेरे द्वारा लिखे गए हैं जो काम नहीं करते हैं। शायद आप एक नज़र डाल सकते हैं। – Digilee

संबंधित मुद्दे