จำลองกระบวนการที่ไม่มีทักษะในสถานะ D


14

สำหรับสถานการณ์การทดสอบหายนะเกี่ยวกับสภาพแวดล้อมของเซิร์ฟเวอร์เรากำลังมองหาวิธีที่ง่ายในการทำให้กระบวนการติดอยู่ในสถานะ D (ไม่หยุดชะงัก)

มีวิธีง่าย ๆ ไหม? ตัวอย่างรหัส C ตัวอย่างจะเป็นเครื่องหมายบวก :)

แก้ไข - คำตอบแรกคือกึ่งถูกต้องเนื่องจากกระบวนการแสดงให้เห็นว่าอยู่ในสถานะ D แต่ยังคงได้รับสัญญาณและสามารถถูกฆ่าได้



ระบบปฏิบัติการใด หรือคุณกำลังมองหาโซลูชันแบบพกพา (ไม่แน่ใจว่ามีหรือไม่)
Derobert

@mr_tron - นี่ไม่ใช่ "uninterruptible" :)
er453r

1
@derobert - ขอโทษที่ไม่แม่นยำ - เซิร์ฟเวอร์ ubuntu 12.04.4
er453r

1
สำหรับผู้ที่กำลังมองหาวิธีแก้ปัญหา "ทำงาน" ไปที่stackoverflow.com/a/22754979/2182622
noname

คำตอบ:


2

ฉันมีปัญหาเดียวกันและแก้ไขได้โดยการสร้างเคอร์เนลโมดูลที่ติดอยู่ในสถานะ D

ขณะที่ผมไม่ได้มีประสบการณ์ใด ๆ ในโมดูลผมเอารหัสจากturorial นี้มีการปรับเปลี่ยนบางส่วนพบว่าบางแห่ง esle

ผลที่ได้คืออุปกรณ์บน / dev / หน่วยความจำที่ติดอ่าน แต่สามารถปลุกขึ้น writting มัน (มันต้องการสองเขียนฉันไม่รู้ว่าทำไม แต่ฉันไม่สนใจ)

ที่จะใช้มันเพียงแค่:

# 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

รหัสสำหรับ memory.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;
}

น่าเสียดายที่ทั้งสองลิงก์เสียชีวิตและไฟล์ที่คัดลอกมาที่นี่ไม่มีทุกอย่าง
Dunatotatos

10

จากhttps://blogs.oracle.com/ksplice/entry/disown_zombie_children_and_the

กระบวนการถูกทำให้อยู่ในโหมดสลีปที่ไม่สามารถขัดจังหวะ (STAT D)เมื่อต้องรอบางสิ่ง(โดยทั่วไปคือ I / O)และไม่ควรจัดการสัญญาณในขณะที่รอ ซึ่งหมายความว่าคุณทำไม่killได้เพราะการฆ่าทั้งหมดส่งสัญญาณ สิ่งนี้อาจเกิดขึ้นในโลกแห่งความเป็นจริงหากคุณถอดปลั๊กเซิร์ฟเวอร์ NFS ของคุณในขณะที่เครื่องอื่นมีการเชื่อมต่อเครือข่ายแบบเปิด

เราสามารถสร้างกระบวนการที่ไม่ จำกัด เวลาของเราเองโดยใช้ประโยชน์จากการ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ขณะที่รายงานจาก


สิ่งที่กำลังมองหา! ขอบคุณมาก!
er453r

3
สิ่งที่น่าเศร้าก็คือกระบวนการอยู่ในสถานะ D แต่ฉันสามารถฆ่ามันได้ด้วยkill: /
er453r

@ er453r - ขอโทษนะผู้ชาย ฉันไม่รู้เกี่ยวกับเรื่องนี้มาก - คำตอบเป็นเพียงแค่คัดลอก / วางซึ่งเป็นสาเหตุที่ฉันตั้งเป็นเนื้อหาของวิกิชุมชน ฉันอ่านคำถามของคุณอยากรู้อยากเห็นตัวเองจากนั้นก็ทำ Google และเปิดสิ่งที่ฉันคิดว่าเป็นข้อมูลที่น่าสนใจ นั่นคือสิ่งที่คุณเห็นด้านบน แต่คะแนนโหวตและส่วนที่เหลือไม่ได้มีส่วนช่วยสร้างชื่อเสียงให้กับตัวเองเพราะมันเป็นแบบไวกิ้งและเพราะฉันขโมยมันไป อาจมีข้อมูลเพิ่มเติมเกี่ยวกับหน้านั้นที่สามารถอธิบายได้ว่าทำไม
mikeserv

ขอบคุณ - ฉันอ่านมันเหมือนที่คุณโพสต์ไว้ ฉันได้ทำการค้นหาทางอินเทอร์เน็ตแล้ว แต่ทุก ๆ คนพยายามที่จะกำจัดกระบวนการนี้ไม่ได้สร้างพวกเขา: P โดยทั่วไปการแลกเปลี่ยนสแต็คมักจะเป็นทางเลือกสุดท้ายสำหรับฉัน :)
er453r

ใช่ฉันยังสามารถฆ่ามันได้เช่นกัน: - /
Leo Ufimtsev

2

โดยทั่วไปคุณไม่สามารถ อ่านบทความนี้หัวข้อ: TASK_KILLABLE: รัฐกระบวนการใหม่ในลินุกซ์

สิ่งที่สกัดมา

เคอร์เนล Linux 2.6.25 แนะนำสถานะกระบวนการใหม่สำหรับการทำให้กระบวนการเข้าสู่โหมดสลีปเรียกว่า TASK_KILLABLE ซึ่งนำเสนอทางเลือกแทน TASK_UNINTERRUPTIBLE ที่มีประสิทธิภาพ แต่ไม่อาจฆ่าได้และง่ายต่อการปลุก แต่ปลอดภัย TASK_INTERRUPTIBLE

คำถามและคำตอบ SO นี้นี้: กระบวนการแบบไม่หยุดชะงักคืออะไร ยังอธิบายมัน

ผมค้นพบนี้ในหนังสือเล่มนี้น่าสนใจมากหัวข้อ: ลินุกซ์ Programming Interface: ลินุกซ์และระบบ UNIX Programming คู่มือ


ไม่ได้หมายความว่าคุณไม่สามารถสร้างกระบวนการที่ไม่สามารถฆ่าได้ หมายความว่าจำนวนการโทรของระบบที่ไม่สามารถทำได้ลดลงเนื่องจากการโทรเหล่านั้นเปลี่ยนเป็นการใช้TASK_KILLABLEสถานะใหม่
Martijn Pieters
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.