One, register character device
[CPP]View Plaincopy
- #define GLOBALMEM_MAJOR 256
- #define Globalmem_size 0X1000//4k
- static int char_major=globalmem_major; Main device number
- struct CHARTEST_DEV
- {
- struct Cdev cdev;
- unsigned char mem[globalmem_size];
- };
- struct Chartest_dev Glob_char_dev; //Global device structure
- Static struct class *char_class=null;
- Static struct Class_device *char_class_dev=null;
- -------------------------------------device open function, match upper function call
- static int Char_open (struct inode *inode, struct file *filp)
- {
- Filp->private_data = &glob_char_dev;
- return 0;
- }
- -------------------------------------read data from the kernel to the user space copy
- Static ssize_t Char_read (struct file* filp,char __user *buf,size_t count,loff_t *ppos)
- {
- unsigned long p=*ppos;
- int ret=0;
- struct Chartest_dev *char_dev=filp->private_data;
- if (p>globalmem_size)//For cross-border inspection
- return 0;
- if (count>globalmem_size-p)//Read more data
- Count=globalmem_size-p;
- if (Copy_to_user (buf, (void*) (char_dev->mem+p), count))
- Ret=-efault;
- Else
- {
- *ppos=*ppos+count;
- Ret=count;
- PRINTK (kern_info "READ%d BYTES (S) from%d", count,p);
- }
- return ret;
- }
- -------------------------------------writing data from the user control to the kernel
- Static ssize_t char_write (struct file* filp,const char __user *buf,size_t count,loff_t *ppos)
- {
- unsigned long p=*ppos;
- int ret=0;
- struct Chartest_dev *char_dev=filp->private_data;
- if (p>globalmem_size)
- return 0;
- if (count>globalmem_size-p)
- Count=globalmem_size-p;
- if (Copy_from_user (char_dev->mem+p,buf,count))
- Ret=-efault;
- Else
- {
- *ppos=*ppos+count;
- Ret=count;
- PRINTK (Kern_info "written%d BYTES (S) from%d", count,p);
- }
- return ret;
- }
- Static loff_t Char_llseek (struct file *filp, loff_t offset, int orig)
- {
- loff_t ret = 0;
- switch (orig)
- {
- Case 0:
- if (offset < 0)
- {
- ret =-EINVAL;
- Break ;
- }
- if ((unsigned int) offset > globalmem_size)
- {
- ret =-EINVAL;
- Break ;
- }
- Filp->f_pos = (unsigned int) offset;
- RET = filp->f_pos;
- Break ;
- Case 1:
- if ((Filp->f_pos + offset) > globalmem_size)
- {
- ret =-EINVAL;
- Break ;
- }
- if ((Filp->f_pos + offset) < 0)
- {
- ret =-EINVAL;
- Break ;
- }
- Filp->f_pos + = offset;
- RET = filp->f_pos;
- Break ;
- Default:
- ret =-EINVAL;
- Break ;
- }
- return ret;
- }
- static const struct file_operations char_fops = {
- . Owner = This_module,
- . Llseek =char_llseek,
- . open = Char_open,
- . Read = Char_read,
- . write = Char_write,
- };
- static void Chartest_setup_cdev ()
- {
- int Err,devno=mkdev (char_major,0);
- Cdev_init (&glob_char_dev.cdev,&char_fops); / * Initialize * /
- Glob_char_dev.cdev.owner=this_module;
- Err=cdev_add (&glob_char_dev.cdev,devno,1);
- if (err<0)
- PRINTK (Kern_notice "ERROR%d ADDING chartest", err);
- Char_class=class_create (This_module,"chartest");
- Char_class_dev=device_create (Char_class,null,devno,null,"Chartest", 0);
- }
- static int char_init (void)
- {
- int result;
- Unsigned long Char_dev_no=mkdev (char_major,0);
- if (char_major) {
- Result=register_chrdev_region (char_dev_no,1,"chartest");
- }
- else{
- Result=alloc_chrdev_region (&char_dev_no,0,1,"chartest");
- Char_major=major (CHAR_DEV_NO);
- }
- PRINTK (Kern_alert "Hello,,we succeed\n");
- if (result<0)
- return result;
- Chartest_setup_cdev ();
- PRINTK (Kern_alert "Hello,,we succeed\n");
- return 0;
- }
- static void Char_exit (void)
- {
- Cdev_del (&glob_char_dev.cdev);
- Unregister_chrdev_region (MKDEV (char_major,0), 1); //zhu XIAO
- Device_unregister (Char_class_dev);
- Class_destroy (Char_class);
- PRINTK (Kern_alert "720 unregister success\n");
- }
- Module_license ("Dual BSD/GPL");
- Module_init (Char_init);
Second, note the point:
The parameter buff of the read and write functions is a pointer to the user space, so the kernel code cannot directly reference the contents, mainly for the following reasons:
1, user-space pointers may not be valid while kernel-mode is running
2, the user space is paged, the content involved may not be in RAM, a direct reference to the memory of the user space may cause page errors
3. Pointers are provided by user space and may be defective.
Copy_to_user () and Copy_from_user () two functions, in addition to the data copy in the kernel space and user space, will also check whether the user space pointer is valid, if the pointer is invalid, not copy, if the copy process encountered an invalid address, will only copy part of the data, In both cases, the return value is a value that also requires a copy of the amount of memory.
[Linux Driver] character device driver learning Note (ii) ——— instance