Попытка заснуть на Linux - PullRequest
       14

Попытка заснуть на Linux

10 голосов
/ 25 июля 2011

Мне нужно исследовать / протестировать поведение некоторого кода в Linux в условиях, когда close может быть прерван обработчиками сигналов (с SA_RESTART или без него).Какова наиболее удобная настройка, чтобы заставить системный вызов close спать в течение измеримого промежутка времени, в течение которого я мог бы попытаться запустить процесс сигналом?Некоторые идеи:

  • Намеренно медленное / не реагирующее монтирование NFS
  • Настраиваемый драйвер FUSE

Но так как это немного затрудняет настройку,Мне интересно, есть ли что-нибудь еще готовое, что могло бы дать желаемое поведение.

1 Ответ

8 голосов
/ 25 июля 2011

Если ни у кого нет идеи получше ...

Вы можете реализовать свой собственный драйвер символьного устройства. Начните с шаблона из Главы 3 в Драйверы устройств Linux (3-е издание) и настройте его, чтобы ничего не делать, кроме блокировки на некоторое время при закрытии (). (Вы можете использовать msleep или msleep_interruptible из главы 7 для блокировки.)

На самом деле, если никто больше не предлагает что-то еще, я, вероятно, могу довольно быстро это исправить, адаптировав существующий код, который у меня есть. Как скоро вам это нужно?

[править]

ОК, попробуйте это ...

Makefile:

ifneq ($(KERNELRELEASE),)
        obj-m := closer.o

else
        KERNELDIR ?= /lib/modules/$(shell uname -r)/build
        PWD := $(shell pwd)

default: modules

%:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) "$@"

.PHONY: default
endif

closer.c:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/fs.h>

MODULE_DESCRIPTION("Block-on-close driver");
MODULE_AUTHOR("Nemo <nemo@self-evident.org>");
MODULE_LICENSE("GPL");
#define VERSION "20110705"
MODULE_VERSION(VERSION);

#define MY_NAME "closer"

int my_open(struct inode *, struct file *);
int my_release(struct inode *, struct file *);
ssize_t my_read(struct file *, char __user *, size_t, loff_t *);
ssize_t my_write(struct file *, const char __user *, size_t, loff_t *);

static struct file_operations my_fops = {
    .owner = THIS_MODULE,
    .open = my_open,
    .read = my_read,
    .write = my_write,
    .release = my_release,
};

static struct miscdevice my_dev;

int __init
my_init(void)
{
    int err = 0;

    printk(KERN_INFO "%s: loading version %s\n", MY_NAME, VERSION);

    my_dev.minor = MISC_DYNAMIC_MINOR;
    my_dev.name = MY_NAME;
    my_dev.fops = &my_fops;
    err = misc_register(&my_dev);

    if (err)
        printk(KERN_ERR "%s: misc_register failed, error %d\n", MY_NAME, err);

    return err;
}

int
my_open(struct inode *inode, struct file *filp)
{
    return 0;
}

ssize_t
my_read(struct file *file, char __user *p, size_t n, loff_t *off) {
    return 0;
}

ssize_t
my_write(struct file *file, const char __user *p, size_t n, loff_t *off) {
    return n;
}

int
my_release(struct inode *inode, struct file *filp)
{
    int err = 0;
    /* 10 second sleep, interruptible. */
    if (msleep_interruptible(10 * 1000) > 0)
        err = -EINTR;

    return err;
}

void __exit
my_exit(void)
{
    misc_deregister(&my_dev);
    printk(KERN_INFO "%s: unloaded\n", MY_NAME);
}

module_init(my_init);
module_exit(my_exit);

Загрузите модуль с помощью «insmod close.o». Если у вас достаточно современная / полная среда Linux, udev автоматически проснется и сгенерирует / dev / ближе. Если нет, вы можете создать узел устройства самостоятельно:

mknod /dev/closer c `tr : ' ' </sys/class/misc/closer/dev`

(то есть / sys / class / misc / close / dev указывает основной: второстепенный для использования.)

Читает и пишет работает как / dev / null; т. е. EOF при любом чтении, успех при любом чтении.

Я убедился, что "cat </ dev / ближе" блокируется в <code>close() на 10 секунд. Я не создал тест, чтобы поймать SIGINT (или что-то еще) и убедиться, что он действительно приводит к EINTR.

Встроено в ядро ​​2.6.32. Дайте мне знать, как это работает для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...