2011-07-25 4 views
8

closeがシグナルハンドラ(SA_RESTARTの有無にかかわらず)で中断される可能性がある条件下で、Linux上のコードの動作を調査/テストする必要があります。 closeがシグナルでプロセスにヒットしようとする可能性のある測定可能な時間の間、syscallをスリープ状態にする最も便利な設定は何ですか?いくつかのアイデア:Linuxでよくスリープしようとしています

  • が非応答/意図的に遅いNFSマウント
  • カスタムFUSE

しかし、これらは、セットアップに痛みのビットをしているので、より多くのオフは何がありますならば、私は思ったんだけど、ドライバ私が使用できるシェルフは、それが望ましい動作を与えることができます。

+0

質問の回答はhttp://stackoverflow.com/questions/40257564/posix-unix-how-to-reliably-close-a-file-descriptorのコードサンプルリンクにあります。この例では、意図的にTCP接続を中断し、パケットを廃棄する必要があります。 close()は、このように数分間分ブロックしておくことができます。 –

答えて

8

誰もがより良いアイデアを持っていない場合は...

独自のキャラクタデバイスドライバを実装することができます。第3章のテンプレートをLinux Device Drivers (3rd edition)から始めて、それを微調整してclose()でしばらくの間ブロックします。

実際には、ほかに他の人が何も示唆していない場合は、私が持っている既存のコードを適応させることで、これをかなり速やかに取り上げることができます。あなたはどれくらいそれを必要としますか?

[編集]

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は近い」を使用してモジュール。 o "。合理的に現代的/完全なLinux環境をお持ちの場合、udevは自動的に起床して/ dev /を生成します。ない場合は、自分でデバイスノードを作成することができます。

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

(つまり、/ SYS /クラス/ miscの/近くには/ devには大きなを示します。マイナー使用する)

読み込みと同じように動作書き込みを/ dev/null;すなわち、任意の読み取りに対するEOF、任意の書き込みに対する成功。

私は、close()に「cat </dev/closer」が10秒間ブロックすることを確認しました。 SIGINT(または何でも)を捕まえるためのテストを作成せず、実際にEINTRという結果が得られることを確認しました。

2.6.32カーネルに対して構築されています。それがあなたのためにどのように機能するか教えてください。

+0

これは急いではありません。私はその間に取り組むことができる他の多くの仕事を持っています。 –

+0

+1 x86_64 2.6.38、Ubuntu 11.04で確認済みです。 (何らかの理由でMakefileが私のために '/ tmp'で動かなかったので、私は手動で' make -C/lib/modules/$(uname -r)/ build M = $(pwd) 'を手動で実行しました。 ) – user786653

+0

ありがとう!どういうわけか私はこれを今までチェックしていなかった。むしろ奇妙な振る舞いです: 'close'がシグナルによって中断されたとき、それは単に0(成功)を返します... –