# Include <Linux/Module. h> # Include <Linux/Types. h> # Include <Linux/fs. h> # Include <Linux/errno. h> # Include <Linux/mm. h> # Include <Linux/sched. h> # Include <Linux/init. h> # Include <Linux/cdev. h> # Include <ASM/IO. h> # Include <ASM/system. h> # Include <ASM/uaccess. h> # Include <Linux/Timer. h> # Include <ASM/Atomic. h># Define second_major 0 Static int second_major = second_major; Struct second_dev { Struct cdev; Atomic_t counter; Struct timer_list s_timer; }; Struct second_dev * second_devp; Static void second_timer_handle (unsigned long Arg) { Mod_timer (& second_devp-> s_timer, jiffies + Hz ); Atomic_inc (& second_devp-> counter ); Printk (kern_err "Current jiffies is % LD/N", jiffies ); } Int second_open (struct inode * inode, struct file * filp) { Init_timer (& second_devp-> s_timer ); Second_devp-> s_timer.function = & second_timer_handle; Second_devp-> s_timer.expires = jiffies + Hz; Add_timer (& second_devp-> s_timer ); Atomic_set (& second_devp-> counter, 0 ); Return 0; } Int second_release (struct inode * inode, struct file * filp) { Del_timer (& second_devp-> s_timer ); Return 0; } Static ssize_t second_read (struct file * filp, char _ User * Buf, size_t count, Loff_t * PPOs) { Int counter; Counter = atomic_read (& second_devp-> counter ); If (put_user (counter, (int *) BUF )) { Return-efault; } Else { Return sizeof (unsigned INT ); } } Static const struct file_operations second_fops = { . Owner = this_module, . Open = second_open, . Release = second_release, . Read = second_read, }; Static void second_setup_cdev (struct second_dev * Dev, int index) { Int err, devno = mkdev (second_major, index ); Cdev_init (& Dev-> cdev, & second_fops ); Dev-> cdev. Owner = this_module; Dev-> cdev. Ops = & second_fops; Err = cdev_add (& Dev-> cdev, devno, 1 ); If (ERR) { Printk (kern_notice "error % d Add second % d", err, index ); } } Int second_init (void) { Int ret; Dev_t devno = mkdev (second_major, 0 ); If (second_major) { Ret = register_chrdev_region (devno, 1, "second "); } Else { Ret = alloc_chrdev_region (& devno, 0, 1, "second "); Second_major = major (devno ); } If (Ret <0) { Return ret; } Second_devp = kmalloc (sizeof (struct second_dev), gfp_kernel ); If (! Second_devp) { Ret =-enomem; Goto fail_malloc; } Memset (second_devp, 0, sizeof (struct second_dev )); Second_setup_cdev (second_devp, 0 ); Return 0; Fail_malloc: Unregister_chrdev_region (devno, 1 ); } Void second_exit (void) { Cdev_del (& second_devp-> cdev ); Kfree (second_devp ); Unregister_chrdev_region (mkdev (second_major, 0), 1 ); } Module_author ("song Baohua "); Module_license ("dual BSD/GPL "); Module_param (second_major, Int, s_irugo ); Module_init (second_init ); Module_exit (second_exit ); Attach the client test program: # Include <stdio. h> # Include <unistd. h> # Include <fcntl. h> Int main (void) { Int FD, I; Int data; FD = open ("/dev/second", o_rdonly ); If (FD <0) { Printf ("Open/dev/second error/N "); } For (I = 0; I <20; I ++) { Read (FD, & Data, sizeof (data )); Printf ("Read/dev/second is % d/N", data ); Sleep (1 ); } Close (FD ); } |