首页 > 代码库 > 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);
View Code
技术分享
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 
View Code

 

技术分享
 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 }
View Code

 

07 字符设备(三)