#include #include #include #include #include #include #include #include #define PROCSNAP_VERSION "0.1" MODULE_DESCRIPTION("Provides snapshots of process data"); MODULE_AUTHOR("Borislav Deianov "); struct proc_struct { pid_t pid; unsigned long state; /* etc */ }; struct snap_struct { struct proc_struct *snapshot; unsigned int len; }; static struct snap_struct *take_snapshot(void) { struct snap_struct *snap; struct proc_struct *ptr; struct task_struct *p; snap = kmalloc(sizeof(*snap), GFP_KERNEL); if (snap == NULL) return NULL; repeat: snap->len = nr_threads * sizeof(struct proc_struct); /* some slack in case nr_threads increases (we get it for free) */ snap->len = PAGE_ALIGN(snap->len); snap->snapshot = vmalloc(snap->len); if (snap->snapshot == NULL) return NULL; read_lock(&tasklist_lock); if (snap->len < nr_threads * sizeof(struct proc_struct)) { read_unlock(&tasklist_lock); vfree(snap->snapshot); goto repeat; } snap->len = nr_threads * sizeof(struct proc_struct); ptr = snap->snapshot; for_each_task(p) { ptr->pid = p->pid; ptr->state = p->state; ptr++; } read_unlock(&tasklist_lock); printk("took snapshot of %d processes\n", snap->len / sizeof(struct proc_struct)); return snap; } static void release_snapshot(void *data) { struct snap_struct *snap = (struct snap_struct *)data; vfree(snap->snapshot); kfree(snap); } static int procsnap_open (struct inode *inode, struct file *file) { MOD_INC_USE_COUNT; if ((file->private_data = take_snapshot()) == NULL) { MOD_DEC_USE_COUNT; return -ENOMEM; } return 0; } static int procsnap_release (struct inode *inode, struct file *file) { release_snapshot(file->private_data); MOD_DEC_USE_COUNT; return 0; } static ssize_t procsnap_read (struct file *file, char *buf, size_t count, loff_t *off) { struct snap_struct *snap = (struct snap_struct *)(file->private_data); if (*off >= snap->len) return 0; if (*off + count > snap->len) count = snap->len - *off; if (copy_to_user(buf, (char *)snap->snapshot + *off, count) < 0) return -EFAULT; *off += count; return count; } static struct file_operations procsnap_fops = { open: procsnap_open, release: procsnap_release, read: procsnap_read, }; static struct miscdevice procsnap_miscdev = { minor: 248, /* XXX get a real minor from HPA */ name: "procsnap", fops: &procsnap_fops, }; static int __init procsnap_init(void) { int error; if ((error = misc_register(&procsnap_miscdev)) < 0) { printk(KERN_ERR "Unable to register procsnap device: %d\n", error); return error; } printk("Procsnap v%s.\n", PROCSNAP_VERSION); return 0; } static void __exit procsnap_cleanup(void) { int error; if ((error = misc_deregister(&procsnap_miscdev)) < 0) printk(KERN_ERR "Unable to deregister procsnap devide : %d\n", error); } module_init(procsnap_init); module_exit(procsnap_cleanup);