डी राज्य में एक अविश्वसनीय प्रक्रिया का अनुकरण करें


14

बाहर सर्वर वातावरण पर तबाही परीक्षण परिदृश्यों के लिए हम एक आसान तरीका डी (अबाधित नींद) स्थिति में फंसाने के लिए देख रहे हैं।

कोई आसान तरीका? एक उदाहरण C नमूना कोड एक प्लस होगा :)

संपादित करें - पहला उत्तर अर्ध-सही है, क्योंकि प्रक्रिया को डी राज्य में दिखाया गया है, लेकिन यह अभी भी संकेत प्राप्त करता है और मारा जा सकता है



किस ऑपरेटिंग सिस्टम पर? या आप एक पोर्टेबल समाधान की तलाश कर रहे हैं (यदि एक है तो सुनिश्चित नहीं है)?
derobert

@mr_tron - यह "निर्बाध" नहीं है :)
er453r

1
@derobert - सटीक नहीं होने के लिए खेद है - ubuntu सर्वर 12.04.4
er453r

1
जो लोग "काम" समाधान की तलाश कर रहे हैं, उनके लिए stackoverflow.com/a/22754979/2182622
noname

जवाबों:


2

मुझे एक ही समस्या थी और इसे एक कर्नेल मॉड्यूल बनाकर हल किया गया जो डी अवस्था में फंस जाता है।

चूंकि मुझे मॉड्यूल में कोई अनुभव नहीं है, इसलिए मैंने इस तिकड़ी से कुछ संशोधनों के साथ कोड लिया, जिसमें कुछ जगह मिली ।

परिणाम / देव / स्मृति पर एक उपकरण है जो पढ़ने पर अटक जाता है, लेकिन इस पर लेखन को जगाया जा सकता है (इसे दो लिखने की आवश्यकता है, मुझे नहीं पता कि मुझे क्यों परवाह है)।

बस इसका उपयोग करने के लिए:

# make
# make mknod
# make install
# cat /dev/memory   # this gets blocked

दूसरे टर्मिनल से अनब्लॉक करने के लिए:

# echo -n a > /dev/memory
# echo -n a > /dev/memory

makefile:

obj-m += memory.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

install:
    sudo insmod memory.ko

uninstall:
    sudo rmmod memory

mknod:
    sudo mknod /dev/memory c 60 0
    sudo chmod 666 /dev/memory

मेमोरी के लिए कोड:

/* Necessary includes for device drivers */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <asm/uaccess.h> /* copy_from/to_user */
#include <linux/sched.h>

MODULE_LICENSE("Dual BSD/GPL");

/* Declaration of memory.c functions */
int memory_open(struct inode *inode, struct file *filp);
int memory_release(struct inode *inode, struct file *filp);
ssize_t memory_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
ssize_t memory_write(struct file *filp, char *buf, size_t count, loff_t *f_pos);
void memory_exit(void);
int memory_init(void);

/* Structure that declares the usual file */
/* access functions */
ssize_t memory_write( struct file *filp, char *buf, size_t count, loff_t *f_pos);
ssize_t memory_read(struct file *filp, char *buf, size_t count, loff_t *f_pos);
int memory_open(struct inode *inode, struct file *filp);
int memory_release(struct inode *inode, struct file *filp);
struct file_operations memory_fops = {
    .read = memory_read,
    .write = memory_write,
    .open = memory_open,
    .release = memory_release
};

/* Declaration of the init and exit functions */
module_init(memory_init);
module_exit(memory_exit);

/* Global variables of the driver */
/* Major number */
int memory_major = 60;
/* Buffer to store data */
char *memory_buffer;

int memory_init(void) {
    int result;

    /* Registering device */
    result = register_chrdev(memory_major, "memory", &memory_fops);
    if (result < 0) {
        printk(
                "<1>memory: cannot obtain major number %d\n", memory_major);
        return result;
    }

    /* Allocating memory for the buffer */
    memory_buffer = kmalloc(1, GFP_KERNEL); 
    if (!memory_buffer) { 
        result = -ENOMEM;
        goto fail; 
    } 
    memset(memory_buffer, 0, 1);

    printk("<1>Inserting memory module\n"); 
    return 0;

fail: 
    memory_exit(); 
    return result;
}

void memory_exit(void) {
    /* Freeing the major number */
    unregister_chrdev(memory_major, "memory");

    /* Freeing buffer memory */
    if (memory_buffer) {
        kfree(memory_buffer);
    }

    printk("<1>Removing memory module\n");

}

int memory_open(struct inode *inode, struct file *filp) {

    /* Success */
    return 0;
}

int memory_release(struct inode *inode, struct file *filp) {

    /* Success */
    return 0;
}
static DECLARE_WAIT_QUEUE_HEAD(wq);
static volatile int flag = 0;

ssize_t memory_read(struct file *filp, char *buf, 
        size_t count, loff_t *f_pos) { 

    printk("<1>going to sleep\n");
    flag = 0;
    //wait_event_interruptible(wq, flag != 0);
    wait_event(wq, flag != 0);

    printk("<1>Reading from memory module\n");
    /* Transfering data to user space */ 
    copy_to_user(buf,memory_buffer,1);

    /* Changing reading position as best suits */ 
    if (*f_pos == 0) { 
        *f_pos+=1; 
        return 1; 
    } else { 
        return 0; 
    }
}

ssize_t memory_write( struct file *filp, char *buf,
        size_t count, loff_t *f_pos) {

    char *tmp;

    printk("<1>wake someone up\n");
    flag = 1;
    //wake_up_interruptible(&wq);
    wake_up(&wq);

    printk("<1>Writting to memory module\n");
    tmp=buf+count-1;
    copy_from_user(memory_buffer,tmp,1);
    return 1;
}

दुर्भाग्य से, दोनों लिंक मृत हैं, और यहां कॉपी की गई फ़ाइलों में सब कुछ नहीं है।
डनोटोटॉस

10

से https://blogs.oracle.com/ksplice/entry/disown_zombie_children_and_the

एक प्रक्रिया एक निर्बाध नींद में डाल दी जाती है(STAT D) जब उसे किसी चीज़ पर प्रतीक्षा करने की आवश्यकता होती है (आमतौर पर I / O) और प्रतीक्षा करते समय संकेतों को संभालना नहीं चाहिए। इसका मतलब यह है कि आप इसे नहीं कर सकते kill, क्योंकि सभी मार करता है यह संकेत भेज रहा है। यह वास्तविक दुनिया में हो सकता है यदि आप अपने एनएफएस सर्वर को अनप्लग करते हैं, जबकि अन्य मशीनों में नेटवर्क कनेक्शन खुला है।

हम vforkसिस्टम कॉल का लाभ उठाकर सीमित अवधि की अपनी निर्बाध प्रक्रियाएं बना सकते हैं । vforkयह पसंद है fork, सिवाय पते के स्थान को माता-पिता से बच्चे में कॉपी नहीं किया जाता है, execजिसकी प्रत्याशा में केवल कॉपी किए गए डेटा को फेंक दिया जाएगा। सुविधाजनक हमारे लिए, जब आप vforkमाता-पिता का इंतजार uninterruptibly (के माध्यम से wait_on_completionबच्चे के पर) execया exit:

jesstess@aja:~$ cat uninterruptible.c 
int main() {
    vfork();
    sleep(60);
    return 0;
}
jesstess@aja:~$ gcc -o uninterruptible uninterruptible.c
jesstess@aja:~$ echo $$
13291
jesstess@aja:~$ ./uninterruptible
and in another shell:

jesstess@aja:~$ ps -o ppid,pid,stat,cmd $(pgrep -f uninterruptible)

13291  1972 D+   ./uninterruptible
 1972  1973 S+   ./uninterruptible

हम बच्चे PID 1973, PPID 1972को एक बाधित नींद में देखते हैं और माता-पिता ( PID 1972, PPID 13291- खोल) को एक निर्बाध नींद में देखते हैं, जबकि यह बच्चे पर 60 सेकंड तक इंतजार करता है।

इस स्क्रिप्ट के बारे में एक साफ-सुथरी (शरारती) बात यह है कि एक मशीन के लिए एक अनियंत्रित नींद में प्रक्रियाएं लोड औसत में योगदान करती हैं। तो आप इस लिपि को 100 बार चला सकते हैं, अस्थायी तौर पर एक मशीन को 100 से बढ़ा हुआ लोड दे सकते हैं, जैसा कि रिपोर्ट किया गया है uptime


वास्तव में क्या देख रहा था! आपका बहुत बहुत धन्यवाद!
एर 453 आर

3
दुखद बात यह है कि यह प्रक्रिया डी स्थिति में है, लेकिन मैं इसे मारने में सक्षम हूं kill: /
er453r

@ er453r - सॉरी, यार। मैं ईमानदारी से इसके बारे में ज्यादा नहीं जानता - जवाब सिर्फ एक कॉपी / पेस्ट था, यही वजह है कि मैंने इसे कम्युनिटी विकी कंटेंट के रूप में सेट किया । मैंने आपके प्रश्न को पढ़ा, स्वयं उत्सुक था, फिर कुछ गुगली की और जो मैंने सोचा वह कुछ बहुत ही रोचक जानकारी थी। जो आप ऊपर देख रहे हैं। लेकिन वोट और बाकी मेरी अपनी प्रतिष्ठा में योगदान नहीं करते हैं क्योंकि यह विकी है, और क्योंकि मैंने इसे चुरा लिया है। हो सकता है कि उस पृष्ठ पर अधिक जानकारी हो जो यह बता सके कि क्यों?
मिकसेर

धन्यवाद - मैंने इसे पढ़ा है जैसे आपने इसे पोस्ट किया है। मैंने इसके लिए पहले ही इंटरनेट खोज लिया है, लेकिन हर कोई इस प्रक्रिया से छुटकारा पाने की कोशिश करता है, उन्हें पैदा नहीं करता है: पी आम तौर पर, स्टैक एक्सचेंज हमेशा मेरे लिए अंतिम उपाय है :)
er453r

हाँ, मैं अब भी इसे मार सकता हूं: - /
लियो उफिमेत्सेव

2

असल में, तुम नहीं कर सकते। इस लेख को पढ़ें: शीर्षक: TASK_KILLABLE: लिनक्स में नई प्रक्रिया स्थिति

अंश

लिनक्स® कर्नेल 2.6.25 ने TASK_KILLABLE नामक नींद के लिए प्रक्रियाएं डालने के लिए एक नई प्रक्रिया राज्य की शुरुआत की, जो कुशल लेकिन संभावित रूप से अनजाने TASK_UNINTERRUPTIBLE और आसान-जागृत लेकिन सुरक्षित TASK_INTERRUPTIBLE को विकल्प प्रदान करता है।

यह SO Q & A शीर्षक: एक निर्बाध प्रक्रिया क्या है? यह भी बताते हैं।

मैंने इस बहुत ही रोचक पुस्तक में इसका पता लगाया जिसका शीर्षक है: द लिनक्स प्रोग्रामिंग इंटरफेस: ए लिनक्स और यूनिक्स सिस्टम प्रोग्रामिंग हैंडबुक


इसका मतलब यह नहीं है कि आप एक अविश्वसनीय प्रक्रिया का उत्पादन नहीं कर सकते। इसका सीधा सा मतलब है कि सिस्टम कॉल की संख्या जो कि अनजानी है, ड्रॉप हो रही है क्योंकि वे कॉल नए TASK_KILLABLEराज्य का उपयोग करने के लिए स्विच करते हैं ।
मार्टिज़न पीटर्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.