【问题标题】:Trying to make close sleep on Linux试图在 Linux 上休眠
【发布时间】:2011-10-12 06:25:07
【问题描述】:

我需要在close 可能被信号处理程序中断的情况下(有或没有SA_RESTART)调查/测试Linux 上某些代码的行为。使close 系统调用休眠一段可测量的时间窗口最方便的设置是什么,在此期间我可以尝试用信号触发进程?一些想法:

  • 故意缓慢/无响应的 NFS 挂载
  • 自定义 FUSE 驱动程序

但是由于这些设置起来有点麻烦,我想知道是否还有其他现成的东西可以使用来提供所需的行为。

【问题讨论】:

  • stackoverflow.com/questions/40257564/… 的代码示例链接中有您的问题的答案。此示例要求您故意中断 TCP 连接,以便丢弃数据包。 close() 可以这样阻塞几分钟。

标签: c linux unit-testing signals


【解决方案1】:

如果没有人有更好的主意......

您可以实现自己的字符设备驱动程序。从Linux Device Drivers (3rd edition) 中第 3 章的模板开始,然后对其进行调整,使其除了在 close() 上阻塞一段时间之外什么都不做。 (您可以使用第 7 章中的 msleepmsleep_interruptible 进行阻塞。)

实际上,如果没有其他人提出其他建议,我可能可以通过调整我现有的一些代码来快速解决这个问题。您多久需要它?

[编辑]

好的,试试这个……

生成文件:

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/closer。如果没有,您可以自己创建设备节点:

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

(即/sys/class/misc/closer/dev 表示要使用的major:minor。)

读写工作类似于/dev/null;即,任何读取都为 EOF,任何写入都成功。

我已验证“cat close() 中阻塞了 10 秒。我还没有创建一个测试来捕获SIGINT(或其他)并验证它是否真的导致EINTR

针对 2.6.32 内核构建。让我知道它是如何为您工作的。

【讨论】:

  • 不急;与此同时,我还有很多其他任务可以完成。
  • +1 在 x86_64 2.6.38、Ubuntu 11.04 上验证。 (尽管出于某种原因,Makefile 对我来说不能只使用 /tmp,所以我只是手动运行 make -C /lib/modules/$(uname -r)/build M=$(pwd)
  • 谢谢!不知何故,我错过了检查这个直到现在。但相当奇怪的行为:当close 被信号中断时,它只返回 0(成功)...
  • 我发现了问题:release的返回值被忽略了。改用flush 方法得到了预期的结果。
  • 有趣...听起来“释放”应该返回“无效”?或者也许这只是一个错误。是否真的应该禁止近距离进行交互睡眠?假期回来我会在内核列表上询问。
猜你喜欢
  • 2016-07-13
  • 2011-07-24
  • 1970-01-01
  • 2011-12-22
  • 2010-12-09
  • 1970-01-01
  • 1970-01-01
  • 2013-01-26
  • 1970-01-01
相关资源
最近更新 更多