Essayer de dormir sur Linux

Je dois examiner / tester le comportement de certains codes sous Linux dans des conditions où close peut être interrompue par des gestionnaires de signaux (avec ou sans SA_RESTART ). Quelle est la configuration la plus pratique pour faire dormir le syscall close pendant une fenêtre de temps mesurable pendant laquelle je pourrais essayer d’atteindre le processus avec un signal? Quelques idées:

  • Montage NFS intentionnellement lent / non réactif
  • Pilote FUSE personnalisé

Mais comme ils sont un peu difficiles à configurer, je me demande s’il y a autre chose que je pourrais utiliser et qui pourrait donner le comportement souhaité.

Si personne d’autre n’a une meilleure idée …

Vous pouvez implémenter votre propre pilote de périphérique de personnage. Commencez avec le modèle du chapitre 3 dans Linux Device Drivers (3rd edition) , et ajustez-le pour ne rien faire d’autre que bloquer pendant un moment sur close (). (Vous pouvez utiliser msleep ou msleep_interruptible partir du chapitre 7 pour effectuer le blocage.)

En fait, si personne d’autre ne suggère autre chose, je peux probablement le faire rapidement en adaptant un code existant. Combien de temps en avez-vous besoin?

[modifier]

OK, essayez ceci …

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 

close.c:

 #include  #include  #include  #include  #include  MODULE_DESCRIPTION("Block-on-close driver"); MODULE_AUTHOR("Nemo "); 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); 

Chargez le module en utilisant “insmod closer.o”. Si vous avez un environnement Linux relativement moderne / complet, udev se réveillera et générera automatiquement / dev / closer. Sinon, vous pouvez créer le nœud de périphérique vous-même:

 mknod /dev/closer c `tr : ' '  

(C'est-à-dire que / sys / class / misc / closer / dev indique le majeur: mineur à utiliser.)

Lit et écrit le travail comme / dev / null; à savoir, EOF sur toute lecture, succès sur toute écriture.

J'ai vérifié que "cat close() pendant 10 secondes. Je n'ai pas créé de test pour détecter SIGINT (ou autre) et vérifier qu'il en résulte réellement EINTR .

Construit avec un kernel 2.6.32. Faites moi savoir comment ça marche pour vous.