D durumunda çalışamaz bir süreç simülasyonu


14

Sunucu dışı ortamdaki felaket testi senaryoları için D (kesintisiz uyku) durumunda sıkışmış bir işlem yapmanın kolay bir yolunu arıyoruz.

Kolay bir yol var mı? Bir örnek C örnek kodu bir artı olur :)

Düzenle - ilk yanıt yarı-doğrudur, çünkü işlem D durumunda olduğu gösterilmiştir, ancak yine de sinyalleri alır ve öldürülebilir



Hangi işletim sisteminde? Yoksa taşınabilir bir çözüm mü arıyorsunuz (bir çözüm olup olmadığından emin değil misiniz)?
derobert

@mr_tron - bu "kesintisiz" değil :)
er453r

1
@derobert - kesin olmadığı için özür dilerim
Ubuntu

1
"Çalışan" bir çözüm arayanlar için stackoverflow.com/a/22754979/2182622
noname

Yanıtlar:


2

Aynı sorunu yaşadım ve D durumunda takılı kalan bir çekirdek modülü oluşturarak çözdüm.

Modüllerde herhangi bir deneyimim olmadığından, esra'da bir yerde bulunan bazı değişikliklerle kodu bu dersden aldım .

Sonuç, / dev / memory üzerinde okumaya yapışan ancak üzerine yazılarak uyandırılabilen bir cihazdır (iki yazma ihtiyacı vardır, neden bilmiyorum ama umrumda değil).

Sadece kullanmak için:

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

Engellemeyi kaldırmak için başka bir terminalden:

# 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

Bellek kodu. C:

/* 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;
}

Ne yazık ki, her iki bağlantı da öldü ve buraya kopyalanan dosyalar her şeyi içermiyor.
Dunatotatos

10

Gönderen https://blogs.oracle.com/ksplice/entry/disown_zombie_children_and_the

Bir işlem bir şey beklemesi gerektiğinde (tipik olarak G / Ç) kesintisiz bir uyku moduna geçer ve beklerken sinyalleri işlememelidir. Bu, yapamayacağınız anlamına gelir , çünkü tüm öldürmeler ona sinyal gönderir. Diğer makinelerde açık ağ bağlantıları varken NFS sunucunuzu çıkarırsanız bu gerçek dünyada olabilir.(STAT D)kill

vforkSistem çağrısından yararlanarak sınırlı süreli kendi kesintisiz süreçlerimizi oluşturabiliriz . vforkgibi forkadres alanı bir beklentisiyle, çocuğun içine ebeveynden kopyalanmaz dışında execsadece kopyalanan verileri dışarı atmak hangi. Uygun bizim için, ne zaman vforkebeveyn bekler sürekli ve (yoluyla wait_on_completionçocuğun üzerine) execveya 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 1972Kesintisiz bir uykuda çocuğu ( ) PID 1972, PPID 13291ve çocuk üzerinde 60 saniye beklerken ebeveyni ( - kabuk) kesintisiz bir uykuda görüyoruz .

Bu komut dosyasıyla ilgili düzgün (yaramaz?) Bir şey, kesintisiz bir uykudaki işlemlerin bir makinenin yük ortalamasına katkıda bulunmasıdır. Bu nedenle, bir makineye bildirdiği gibi, bir makineye geçici olarak 100 yükseltilmiş bir yük ortalaması vermek için bu komut dosyasını 100 kez çalıştırabilirsiniz uptime.


Tam olarak ne arıyordu! Çok teşekkür ederim!
er453r

3
üzücü olan şey sürecin D durumunda olmasıdır, ama ile öldürmek mümkün kill: /
er453r

@ er453r - üzgünüm, adamım. Dürüstçe çok şey bilmiyorum - cevap sadece bir kopyala / yapıştırdı, bu yüzden topluluk wiki içeriği olarak ayarladım . Sorunuzu okudum, kendimi merak ettim, sonra biraz googling yaptım ve oldukça ilginç bilgiler olduğunu düşündüğüm şeyi buldum. Yukarıda gördüğünüz şey bu. Ama oylar ve geri kalanı kendi itibarıma katkıda bulunmuyor çünkü vikili ve bir tür çalıyorum. Belki de o sayfada nedenini açıklayabilecek daha fazla bilgi var?
mikeserv

Teşekkürler - Siz de yayınladığınız gibi okudum. Bunu zaten internette aradım, ama her biri bu süreçlerden kurtulmaya çalışıyor, onları yaratmaya çalışmıyor: P Genel olarak, yığın değişimi her zaman benim için son çare :)
er453r

Evet, yine de bunu öldürebilirim: - /
Leo Ufimtsev

2

Temel olarak, yapamazsınız. Şu makaleyi okuyun: TASK_KILLABLE: Linux'ta yeni işlem durumu .

alıntı

Linux® çekirdeği 2.6.25, verimli ancak potansiyel olarak çözülemeyen TASK_UNINTERRUPTIBLE ve kolay uyan ancak daha güvenli TASK_INTERRUPTIBLE'a alternatifler sunan TASK_KILLABLE adlı işlemleri uykuya sokmak için yeni bir işlem durumu sundu.

Bu SO Soru-Cevap başlıklı: Kesintisiz süreç nedir? ayrıca açıklıyor.

Bunu şu ilginç kitapta keşfettim: Linux Programlama Arayüzü: Bir Linux ve UNIX Sistem Programlama El Kitabı .


Bu, çözülemez bir süreç üretemeyeceğiniz anlamına gelmez. Bu sadece yeni TASK_KILLABLEdurumun kullanımına geçilirken, unkillable olan sistem çağrılarının sayısının düştüğü anlamına gelir .
Martijn Pieters
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.