D 상태에서 처리 할 수없는 프로세스 시뮬레이션


14

서버 외부 환경에서의 재난 테스트 시나리오를 위해 프로세스를 D (무정전 절전 모드) 상태에 빠뜨리는 쉬운 방법을 찾고 있습니다.

쉬운 방법이 있습니까? 예제 C 샘플 코드는 플러스입니다. :)

편집 -프로세스가 D 상태 인 것으로 표시되어 있지만 여전히 신호를 수신하여 종료 될 수 있으므로 첫 번째 답변은 반올림입니다.



어떤 운영 체제에서? 아니면 휴대용 솔루션을 찾고 있습니까?
derobert

@mr_tron- "uninterruptible"이 아닙니다 :)
er453r

1
@derobert-정확하지 않아 죄송합니다-우분투 서버 12.04.4
er453r

1
"작동하는"솔루션을 찾는 사람들을 위해 stackoverflow.com/a/22754979/2182622
noname

답변:


2

나는 같은 문제가 있었고 D 상태에서 멈추는 커널 모듈을 만들어서 해결했습니다.

모듈에 대한 경험 이 없기 때문에이 turorial 에서 코드를 가져 와서 esle 을 발견 했습니다 .

결과는 / dev / memory의 장치가 읽히지 만 깨어날 수 있습니다 (두 번의 쓰기가 필요합니다. 왜 그런지 모르겠지만 신경 쓰지 않습니다).

그냥 사용하려면 :

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

다른 터미널에서 차단을 해제하려면

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

메이크 파일 :

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

10

에서 https://blogs.oracle.com/ksplice/entry/disown_zombie_children_and_the

프로세스는 무언가를 기다려야 할 때 (일반적으로 I / O) 중단없이 대기 (STAT D) 상태가되며 대기하는 동안 신호를 처리해서는 안됩니다. 이것은 모든 킬이 신호를 보내기 때문에 할 수 없다는 것을 의미합니다 . 다른 머신이 네트워크에 연결되어있는 동안 NFS 서버를 분리하면 실제 상황에서 발생할 수 있습니다.kill

vfork시스템 호출 을 활용하여 기간이 한정된 자체 무정전 프로세스를 작성할 수 있습니다 . vfork처럼 fork주소 공간가 예상 자식으로 부모로부터 복사되지 않습니다 제외하고, exec단지 복사 된 데이터를 던질 것이다. 편리하게 우리를 위해, vfork부모 가 자녀의 방해없이 ( 또는 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 1329160 초 동안 대기하는 동안 중단 가능한 수면에서 자식 ( )과 중단되지 않은 수면에서 부모 ( -셸)를 볼 수 있습니다.

이 스크립트에 대한 한 가지 깔끔한 (불확실한) 문제는 무정전 절전 모드의 프로세스가 시스템의로드 평균에 기여한다는 것입니다. 따라서이 스크립트를 100 번 실행하여에 의해보고 된대로 일시적으로 시스템에로드 평균을 100 씩 올릴 수 있습니다 uptime.


정확히 무엇을 찾고 있었습니까! 대단히 감사합니다!
er453r

3
슬픈 것은 프로세스가 D 상태에 있다는 것입니다,하지만 난 그것을 죽일 수 있어요 kill: /
er453r

@ er453r-죄송합니다. 나는 솔직히 그것에 대해 많이 알지 못합니다-대답은 복사 / 붙여 넣기 일뿐이므로 커뮤니티 위키 컨텐츠 로 설정했습니다 . 나는 당신의 질문을 읽고, 호기심이 많았고, 인터넷 검색을하고 꽤 흥미로운 정보라고 생각했던 것을 밝혀 냈습니다. 그것이 위에서 본 것입니다. 그러나 투표와 나머지는 위키가 있기 때문에, 그리고 나는 그것을 훔 쳤기 때문에 내 명성에 기여하지 않습니다. 어쩌면 그 페이지에 더 많은 정보가 있는데 그 이유를 설명해 주시겠습니까?
mikeserv 2016 년

감사합니다-게시 한 그대로 읽었습니다. 이미 이것에 대한 인터넷을 검색했지만 모두 시도가이 프로세스를 제거하는 그들을 만들 수 없습니다 : P는 일반적으로 스택 교환은 항상 :) 나를 위해 최후의 수단이다
er453r

그래, 나도 이것을 죽일 수있다 :-/
Leo Ufimtsev

2

기본적으로는 할 수 없습니다. TASK_KILLABLE : Linux의 새 프로세스 상태 라는 제목의 기사를 읽으십시오 .

발췌

Linux® 커널 2.6.25는 TASK_KILLABLE이라는 프로세스를 휴면 상태로 전환하기위한 새로운 프로세스 상태를 도입했습니다. 이는 TASK_UNINTERRUPTIBLE의 효율적이지만 잠재적으로 불가능한 TASK_INTERRUPTIBLE에 대한 대안을 제공합니다.

이 SO Q & A는 제목 : 무정전 프로세스 란 무엇입니까? 또한 설명합니다.

나는이 흥미로운 책에서 리눅스 프로그래밍 인터페이스 : 리눅스와 유닉스 시스템 프로그래밍 핸드북 에서 이것을 발견했다 .


그렇다고 죽일 수없는 프로세스를 만들 수 없다는 의미는 아닙니다. 이는 호출이 새로운 TASK_KILLABLE상태 를 사용하도록 전환함에 따라 킬 수없는 시스템 호출 수가 줄어들고 있음을 의미합니다 .
Martijn Pieters
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.