我需要调查/测试Linux上某些代码的行为,在close
可能被信号处理程序中断的情况下(有或没有SA_RESTART
)。在一段可测量的时间窗口内close
系统调用睡眠的最方便的设置是什么?在此期间,我可以尝试用信号命中该过程?一些想法:
但是由于这些设置有点痛苦,我想知道是否有更多现成的我可以使用它可以提供所需的行为。
答案 0 :(得分:8)
如果没有其他人有更好的主意......
您可以实现自己的角色设备驱动程序。从Linux Device Drivers (3rd edition)中第3章的模板开始,调整它除了在close()上暂停一段时间外什么都不做。 (您可以使用第7章中的msleep
或msleep_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 closer.o”加载模块。如果您有一个相当现代/完整的Linux环境,udev将自动唤醒并生成/ dev / close。如果没有,您可以自己创建设备节点:
mknod /dev/closer c `tr : ' ' </sys/class/misc/closer/dev`
(即/ sys / class / misc / closer / dev表示要使用的major:minor。)
读取和写入/ dev / null之类的工作;即任何阅读的EOF,任何写作的成功。
我已经验证“{&lt; / dev / closer”在close()
中阻止了10秒钟。我没有创建一个测试来捕获SIGINT
(或其他),并验证它实际上是EINTR
的结果。
针对2.6.32内核构建。让我知道它对你有用。