首页 > 代码库 > 07 字符设备(三)
07 字符设备(三)
不足之处有:
(1)char_device是在data段分配的,占用很大空间。
改善:char_device的空间在Linux内核的堆区分配。
(2)字符设备的读写函数接口,没有实际的数据流向。
改善:xxx_read函数接口将buffer内容拷贝到用户空间,xxx_write函数接口将用户空间传下的数据,写到buffer里面。
(3)没有xxx_ioctl接口
(4)只有一个设备
一、内核空间动态分配空间
/**
* kmalloc - allocate memory
* @size: how many bytes of memory are required.
* @flags: the type of memory to allocate.
*
* kmalloc is the normal method of allocating memory
* for objects smaller than page size in the kernel.
*
*/
static __always_inline void *kmalloc(size_t size, gfp_t flags)
头文件:#include <linux/slab.h>
/**
* kzalloc - allocate memory. The memory is set to zero.
* @size: how many bytes of memory are required.
* @flags: the type of memory to allocate (see kmalloc).
*/
static inline void *kzalloc(size_t size, gfp_t flags)
头文件:#include <linux/slab.h>
功能:
/**
* kfree - free previously allocated memory
* @objp: pointer returned by kmalloc.
*
* If @objp is NULL, no operation is performed.
*
* Don‘t free memory not originally allocated by kmalloc()
* or you will run into trouble.
*/
void kfree(const void *objp)
头文件:#include <linux/slab.h>
/**
* krealloc - reallocate memory. The contents will remain unchanged.
* @p: object to reallocate memory for.
* @new_size: how many bytes of memory are required.
* @flags: the type of memory to allocate.
*
* The contents of the object pointed to are preserved up to the
* lesser of the new and old sizes. If @p is %NULL, krealloc()
* behaves exactly like kmalloc(). If @new_size is 0 and @p is not a
* %NULL pointer, the object pointed to is freed.
*/
void *krealloc(const void *p, size_t new_size, gfp_t flags)
二、用户空间和内核空间数据拷贝
三、用户空间和内核空间数据拷贝
#define access_ok(type, addr, size) __access_ok((unsigned long)(addr),(size))
static inline long copy_from_user(void *to, const void __user * from, unsigned long n)
static inline long copy_to_user(void __user *to,const void *from, unsigned long n)
#define put_user(x, ptr)
#define get_user(x, ptr)
1 #include <linux/module.h> 2 #include <linux/init.h> 3 #include <linux/cdev.h> 4 #include <linux/fs.h> 5 #include <linux/device.h> 6 #include <linux/uaccess.h> 7 #include <asm-generic/ioctl.h> 8 #include "head.h" 9 10 MODULE_LICENSE("GPL"); 11 12 #define MAX 1024 13 14 struct mycdev 15 { 16 dev_t dev_num; 17 int len; 18 char kbuf[MAX]; 19 struct cdev cdev; 20 struct class *cls; 21 struct device *device; 22 }; 23 24 struct mycdev cdev_device; 25 26 //int (*open) (struct inode *, struct file *); 27 int mycdev_open(struct inode *inode,struct file *file) 28 { 29 printk("Call mycdev_open()\n"); 30 31 return 0; 32 } 33 34 //ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); 35 ssize_t mycdev_read(struct file *file,char __user *ubuf,size_t size,loff_t *offset) 36 { 37 int len; 38 39 printk("Call mycdev_read()\n"); 40 //copy_to_user(void __user * to, const void * from, unsigned long n) 41 42 if(size >= cdev_device.len) 43 len = cdev_device.len; 44 else 45 len = size; 46 47 if(copy_to_user(ubuf,cdev_device.kbuf,len) != 0) 48 { 49 printk("Fail to copy_to_user()"); 50 return -EFAULT; 51 } 52 53 54 return len; 55 } 56 57 //ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); 58 ssize_t mycdev_write(struct file *file,const char __user *ubuf,size_t size,loff_t *offset) 59 { 60 printk("call mycdev_write()\n"); 61 62 if(size >= MAX) 63 return -1; 64 65 //copy_from_user(void *to, const void * __user from, unsigned long n) 66 if(copy_from_user(cdev_device.kbuf,ubuf,size) != 0) 67 { 68 printk("Fail to copy_from_user()"); 69 return -EFAULT; 70 } 71 cdev_device.kbuf[size] = ‘\0‘; 72 printk("write : %s\n",cdev_device.kbuf); 73 74 cdev_device.len = size; 75 76 return size; 77 } 78 79 //long (*unlocked_ioctl) (struct file *file, unsigned int cmd, unsigned long arg); 80 long mycdev_unlocked_ioctl(struct file *file,unsigned int cmd, unsigned long arg) 81 { 82 int ret = 0; 83 84 switch(cmd) 85 { 86 case CMD_CDEV_CLEAN: 87 memset(cdev_device.kbuf,0,MAX); 88 printk("CMD_CLEN\n"); 89 break; 90 91 case CMD_SET_CDEV_LEN: 92 cdev_device.len = arg; 93 printk("CMD_SET\n"); 94 break; 95 96 case CMD_GET_CDEV_LEN: 97 put_user(cdev_device.len,(unsigned long *)arg); 98 printk("CMD_GET\n"); 99 break; 100 101 default: 102 printk("INvalid\n"); 103 ret = -EINVAL; 104 break; 105 } 106 107 return ret; 108 } 109 110 //int (*release) (struct inode *, struct file *); 111 int mycdev_release(struct inode *inode,struct file *file) 112 { 113 printk("Call mycdev_release()\n"); 114 return 0; 115 } 116 117 118 struct file_operations fops = { 119 .owner = THIS_MODULE, 120 .open = mycdev_open, 121 .read = mycdev_read, 122 .write = mycdev_write, 123 .release = mycdev_release, 124 .unlocked_ioctl = mycdev_unlocked_ioctl, 125 }; 126 127 128 int mycdev_init(void) 129 { 130 int ret; 131 132 //cdev_init(struct cdev * cdev, const struct file_operations * fops) 133 cdev_init(&cdev_device.cdev,&fops); 134 135 136 //alloc_chrdev_region(dev_t * dev, unsigned baseminor, unsigned count, const char * name) 137 ret = alloc_chrdev_region(&cdev_device.dev_num,0,1,"mycdev"); 138 if(ret != 0){ 139 printk("Fail to alloc_chrdev_region()\n"); 140 goto err_alloc_chrdev_region; 141 } 142 143 144 //cdev_add(struct cdev * p, dev_t dev, unsigned count) 145 ret = cdev_add(&cdev_device.cdev,cdev_device.dev_num,1); 146 if(ret != 0){ 147 printk("Fail to cdev_add\n"); 148 goto err_cdev_add; 149 150 } 151 152 //class_create(owner, name) /sys/class/mycdev 153 cdev_device.cls = class_create(THIS_MODULE,"mycdev"); 154 if(IS_ERR(cdev_device.cls)){ 155 printk("Fail to class_create()"); 156 ret = PTR_ERR(cdev_device.cls); 157 goto err_class_create; 158 } 159 160 //device_create(struct class * cls, struct device * parent, dev_t devt, void * drvdata, const char * fmt,...) 161 cdev_device.device = device_create(cdev_device.cls,NULL,cdev_device.dev_num,NULL,"mycdev_device"); 162 if(IS_ERR(cdev_device.device)){ 163 printk("Fail to device_create()"); 164 ret = PTR_ERR(cdev_device.device); 165 goto err_device_create; 166 } 167 168 return 0; 169 170 err_device_create: 171 class_destroy(cdev_device.cls); 172 173 err_class_create: 174 cdev_del(&cdev_device.cdev); 175 176 err_cdev_add: 177 //unregister_chrdev_region(dev_t from, unsigned count) 178 unregister_chrdev_region(cdev_device.dev_num,1); 179 180 err_alloc_chrdev_region: 181 return ret; 182 } 183 184 185 void mycdev_exit(void) 186 { 187 device_destroy(cdev_device.cls, cdev_device.dev_num); 188 class_destroy(cdev_device.cls); 189 //cdev_del(struct cdev * p) 190 cdev_del(&cdev_device.cdev); 191 unregister_chrdev_region(cdev_device.dev_num,1); 192 193 return ; 194 } 195 196 197 module_init(mycdev_init); 198 module_exit(mycdev_exit);
1 #ifndef _HEAD_H_ 2 #define _HEAD_H_ 3 4 #define CMD_TYPE ‘k‘ 5 #define CMD_CDEV_CLEAN _IO(CMD_TYPE,0x10) 6 #define CMD_SET_CDEV_LEN _IOW(CMD_TYPE,0x11,int) 7 #define CMD_GET_CDEV_LEN _IOR(CMD_TYPE,0x12,int) 8 9 #endif
1 #include <sys/types.h> 2 #include <sys/stat.h> 3 #include <fcntl.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <sys/ioctl.h> 7 #include "head.h" 8 9 int main(int argc, const char *argv[]) 10 { 11 int n; 12 int fd; 13 int pid; 14 int len; 15 char buf[1024]; 16 char *string = "hello word\n"; 17 18 fd = open("/dev/mycdev_device",O_RDWR); 19 printf("fd = %d\n",fd); 20 21 n = write(fd,string,strlen(string)); 22 printf("n = %d\n",n); 23 24 n = read(fd,buf,sizeof(buf)); 25 printf("n = %d\n",n); 26 27 ioctl(fd,CMD_CDEV_CLEAN); 28 ioctl(fd,CMD_SET_CDEV_LEN,100); 29 ioctl(fd,CMD_GET_CDEV_LEN,&len); 30 printf("len = %d\n",len); 31 32 33 return 0; 34 }
07 字符设备(三)