1 #include <linux/module.h> 2 #include <linux/init.h> 3 #include <linux/fs.h> 4 #include <linux/cdev.h> 5 6 #include <linux/wait.h> 7 #include <linux/sched.h> 8 9 #include <asm/uaccess.h> 10 #include <linux/errno.h> 11 12 #define DEBUG_SWITCH 1 13 #if DEBUG_SWITCH 14 #define P_DEBUG(fmt, args...) printk("<1>" "<kernel>[%s]"fmt, __FUNCTION__, ##args) 15 #else 16 #define P_DEBUG(fmt, args...) printk("<7>" "<kernel>[%s]"fmt, __FUNCTION__, ##args) 17 #endif 18 19 #define DEV_SIZE 100 20 21 struct _test_t{ 22 char kbuf[DEV_SIZE]; 23 unsigned int major; 24 unsigned int minor; 25 unsigned int cur_size; 26 dev_t devno; 27 struct cdev test_cdev; 28 wait_queue_head_t test_queue; //1銆佸畾涔夌瓑寰呴槦鍒楀ご 29 }; 30 31 int test_open(struct inode *node, struct file *filp) 32 { 33 struct _test_t *dev; 34 dev = container_of(node->i_cdev, struct _test_t, test_cdev); 35 filp->private_data = dev; 36 return 0; 37 } 38 39 int test_close(struct inode *node, struct file *filp) 40 { 41 return 0; 42 } 43 44 ssize_t test_read(struct file *filp, char __user *buf, size_t count, loff_t *offset) 45 { 46 int ret; 47 struct _test_t *dev = filp->private_data; 48 49 /*浼戠湢*/ 50 P_DEBUG("read data.....\\n"); 51 if(wait_event_interruptible(dev->test_queue, dev->cur_size > 0)) 52 return - ERESTARTSYS; 53 54 if (copy_to_user(buf, dev->kbuf, count)){ 55 ret = - EFAULT; 56 }else{ 57 ret = count; 58 dev->cur_size -= count; 59 P_DEBUG("read %d bytes, cur_size:[%d]\\n", count, dev->cur_size); 60 } 61 62 return ret; //杩斿洖瀹為檯鍐欏叆鐨勫瓧鑺傛暟鎴栭敊璇彿 63 } 64 65 ssize_t test_write(struct file *filp, const char __user *buf, size_t count, loff_t *offset) 66 { 67 int ret; 68 struct _test_t *dev = filp->private_data; 69 70 if(copy_from_user(dev->kbuf, buf, count)){ 71 ret = - EFAULT; 72 }else{ 73 ret = count; 74 dev->cur_size += count; 75 P_DEBUG("write %d bytes, cur_size:[%d]\\n", count, dev->cur_size); 76 P_DEBUG("kbuf is [%s]\\n", dev->kbuf); 77 /*鍞ら啋*/ 78 wake_up_interruptible(&dev->test_queue); 79 } 80 81 return ret; //杩斿洖瀹為檯鍐欏叆鐨勫瓧鑺傛暟鎴栭敊璇彿 82 } 83 84 struct file_operations test_fops = { 85 .open = test_open, 86 .release = test_close, 87 .write = test_write, 88 .read = test_read, 89 }; 90 91 struct _test_t my_dev; 92 93 static int __init test_init(void) //妯″潡鍒濆鍖栧嚱鏁? 94 { 95 int result = 0; 96 my_dev.cur_size = 0; 97 my_dev.major = 0; 98 my_dev.minor = 0; 99 100 if(my_dev.major){ 101 my_dev.devno = MKDEV(my_dev.major, my_dev.minor); 102 result = register_chrdev_region(my_dev.devno, 1, "test new driver"); 103 }else{ 104 result = alloc_chrdev_region(&my_dev.devno, my_dev.minor, 1, "test alloc diver"); 105 my_dev.major = MAJOR(my_dev.devno); 106 my_dev.minor = MINOR(my_dev.devno); 107 } 108 109 if(result < 0){ 110 P_DEBUG("register devno errno!\\n"); 111 goto err0; 112 } 113 114 printk("major[%d] minor[%d]\\n", my_dev.major, my_dev.minor); 115 116 cdev_init(&my_dev.test_cdev, &test_fops); 117 my_dev.test_cdev.owner = THIS_MODULE; 118 /*鍒濆鍖栫瓑寰呴槦鍒楀ご锛屾敞鎰忓嚱鏁拌皟鐢ㄧ殑浣嶇疆*/ 119 init_waitqueue_head(&my_dev.test_queue); 120 121 result = cdev_add(&my_dev.test_cdev, my_dev.devno, 1); 122 if(result < 0){ 123 P_DEBUG("cdev_add errno!\\n"); 124 goto err1; 125 } 126 127 printk("hello kernel\\n"); 128 return 0; 129 130 err1: 131 unregister_chrdev_region(my_dev.devno, 1); 132 err0: 133 return result; 134 } 135 136 static void __exit test_exit(void) //妯″潡鍗歌浇鍑芥暟 137 { 138 cdev_del(&my_dev.test_cdev); 139 unregister_chrdev_region(my_dev.devno, 1); 140 141 printk("good bye kernel\\n"); 142 } 143 144 module_init(test_init); 145 module_exit(test_exit); 146 147 MODULE_LICENSE("GPL"); 148 MODULE_AUTHOR("xoao bai"); 149 MODULE_VERSION("v0.1");
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 6 int main(void) 7 { 8 char buf[20]; 9 int fd; 10 int ret; 11 12 fd = open("/dev/test", O_RDWR); 13 if(fd < 0) 14 { 15 perror("open"); 16 return -1; 17 } 18 19 read(fd, buf, 10); 20 printf("<app>buf is [%s]\\n", buf); 21 22 close(fd); 23 return 0; 24 }
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 6 int main(void) 7 { 8 char buf[20]; 9 int fd; 10 int ret; 11 12 fd = open("/dev/test", O_RDWR); 13 if(fd < 0) 14 { 15 perror("open"); 16 return -1; 17 } 18 19 write(fd, "xiao bai", 10); 20 21 close(fd); 22 return 0; 23 }
验证: [root: 1st]# insmod test.ko major[253] minor[0] hello kernel [root: 1st]# mknod /dev/test c 253 0 [root: 1st]# ./app_read & //&表示后台运行app_read [test_read]read data..... //因为没有数据,程序阻塞 [root: 1st]# ./app_write //再运行app_write [test_write]write 10 bytes, cur_size:[10] [test_write]kbuf is [xiao bai] [test_read]read 10 bytes, cur_size:[0] //read继续执行 buf is [xiao bai] //打印读到的内容 [1] + Done ./app_read [root: 1st]#
http://blog.chinaunix.net/uid-25014876-id-60025.html