📄 copy_xx_user.c
字号:
/* 马上练习 copy_to_user/copy_from_user()的用法,毕竟put_user()/get_user()的效率有点低, 而且老加上while()循环,不好看 */ //#define KERNEL_DEBUG#include <linux/kernel.h>#include <linux/module.h>#include <linux/fs.h>#include <asm/uaccess.h> /* for put_user */#include <linux/init.h>#define KERNEL_DEBUG#include "mod_head.h"/** Prototypes - this would normally go in a .h file*/static __init int chardev_init(void);static __exit void chardev_exit(void);static int device_open(struct inode *, struct file *);static int device_release(struct inode *, struct file *);static ssize_t device_read(struct file *, char *, size_t, loff_t *);static ssize_t device_write(struct file *, const char *, size_t, loff_t *);#define SUCCESS 0#define DEVICE_NAME "chardev_bob_test" /* Dev name as it appears in /proc/devices */#define BUF_LEN 6 /* Max length of the message from the device *//** Global variables are declared as static, so are global within the file.*/static int Major; /* Major number assigned to our device driver */static char msg[BUF_LEN] = {'\0'}; /* The msg the device will give when asked */static char *msg_Ptr;static volatile unsigned long chardev_users = 0UL; //防止互斥, 这里用更严格的test_and_set_bit() 函数static int device_open(struct inode *inode, struct file *file){ // if (Device_Open) // return -EBUSY; // Device_Open++; // 上面的办法太不可靠了。用原子操作或者bit操作才是最可靠的。 if(test_and_set_bit(0,&chardev_users)) return -EBUSY; msg_Ptr = msg; try_module_get(THIS_MODULE); return SUCCESS;}static int device_release(struct inode *inode, struct file *file){ if( !test_and_clear_bit(0,&chardev_users)) { //如果value还为1,就错了 dbg("It looks that the bit operation is wrong \n"); return -1; } module_put(THIS_MODULE); return 0;}static ssize_t device_read(struct file *filp, /* see include/linux/fs.h */ char *buffer, /* buffer to fill with data */ size_t length, /* length of the buffer */ loff_t * offset) /* loff_t == long long */{ // Number of bytes actually written to the buffer int bytes_read = 0; if (*msg_Ptr == 0) return 0;// while (length && *msg_Ptr) {//// // kernel ----> user// put_user(*(msg_Ptr++), buffer++);//// length--;// bytes_read++;// } /* copy_to_user() 的用法很简单 */ dbg("msg_Ptr length=%d\n",strlen(msg_Ptr)); if(copy_to_user(buffer,msg_Ptr, min(strlen(msg_Ptr),length))) { dbg("copy_to_user() error \n"); return -EFAULT; } bytes_read = min(strlen(msg_Ptr),length); return bytes_read; }static ssize_tdevice_write(struct file *filp, const char *buffer, size_t len, loff_t * off){ int bytes_write = 0; int max_bytes = sizeof(msg) -1; memset(msg,'\0',sizeof(msg));// while( *buffer && bytes_write < len && bytes_write < max_bytes )// { // // kernel <---user// get_user(*(msg_Ptr++),buffer++);//msg_Ptr[i] is same// bytes_write++;// } copy_from_user(msg_Ptr,buffer, min( min(strlen(buffer),len), sizeof(msg)-1)); bytes_write = min( min(strlen(buffer),len), sizeof(msg)-1 ); dbg("write %d bytes \n",bytes_write); return bytes_write;}static struct file_operations fops = { .owner = THIS_MODULE, .read = device_read, .write = device_write, .open = device_open,// .ioctl = device_ioctl, //bob add to get pid of some process .release= device_release //others are NULL;};/** Functions*/static __init int chardev_init(void){ Major = register_chrdev(0, DEVICE_NAME, &fops); if (Major < 0) { dbg("Registering the character device failed with %d\n", Major); return Major; } dbg("I was assigned major number %d. To talk to\n", Major); dbg("the driver, create a dev file with\n"); dbg("'mknod /dev/hello c %d 0'.\n", Major); dbg("Try various minor numbers. Try to cat and echo to\n"); dbg("the device file.\n"); dbg("Remove the device file and module when done.\n"); return 0;}static __exit void chardev_exit(void){ int ret = unregister_chrdev(Major, DEVICE_NAME); if (ret < 0) dbg("Error in unregister_chrdev: %d\n", ret);}module_init(chardev_init);module_exit(chardev_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -