我需要在信號處理程序(無論是否帶有SA_RESTART
)可能會中斷close
的條件下調查/測試Linux上某些代碼的行爲。什麼是最方便的設置,可以讓系統調用睡眠一段可測量的時間窗口,在此期間我可以嘗試用信號來觸發過程?一些想法:試圖在Linux上關閉睡眠
- 故意慢/無響應的NFS掛載
- 定製FUSE驅動
但由於這些都是一個痛苦位設置的,我想知道如果有什麼更多的關我可以使用可以提供所需行爲的貨架。
我需要在信號處理程序(無論是否帶有SA_RESTART
)可能會中斷close
的條件下調查/測試Linux上某些代碼的行爲。什麼是最方便的設置,可以讓系統調用睡眠一段可測量的時間窗口,在此期間我可以嘗試用信號來觸發過程?一些想法:試圖在Linux上關閉睡眠
但由於這些都是一個痛苦位設置的,我想知道如果有什麼更多的關我可以使用可以提供所需行爲的貨架。
如果沒有其他人有更好的主意...
你可以實現自己的字符設備驅動程序。從Linux Device Drivers (3rd edition)的第3章中的模板開始,調整它在close()上除了block之外什麼也不做。 (你可以使用第7章中的msleep
或msleep_interruptible
來進行阻塞。)
實際上,如果沒有其他人提出其他建議,我可以通過調整現有代碼來快速調整它。你多久需要它?
[編輯]
OK,試試這個...
的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) "[email protected]"
.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 <[email protected]>");
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的接近模塊。 ○」。如果你有一個合理的現代/完整的Linux環境,udev會自動喚醒併產生/ dev/close。如果沒有,你可以自己創建的設備節點:
mknod /dev/closer c `tr : ' ' </sys/class/misc/closer/dev`
(也就是說,/ SYS /類/其它/接近的/ dev表示主:未成年人使用)
讀,喜歡寫工作的/ dev/null的;即任何讀取時的EOF,任何寫入都成功。
我已經驗證了「cat </dev/closer」在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)' ) – user786653
謝謝!不知何故,我錯過了檢查,直到現在。相當奇怪的行爲:當close被信號中斷時,它只返回0(成功)... –
在http://stackoverflow.com/questions/40257564/posix-unix-how-to-reliably-close-a-file-descriptor中的代碼示例鏈接中存在對您的問題的回答。這個例子要求你故意中斷一個TCP連接,這樣數據包就會被丟棄。 close()可以通過這種方式阻止分鐘。 –