/*
驱动模块代码
*/
#include <linux/init.h>
#include <linux/module.h>#include <linux/uaccess.h>
#include <linux/fs.h>
#define SUCCESS 0
#define DEVICE_NAME "charDev"
#define BUF_LEN 80
MODULE_AUTHOR("HWM");
MODULE_LICENSE("GPL");
static int Major;
static int device_Open = 0;
static char msg[BUF_LEN];
static char *msg_ptr = 0;
static int open_count = 0;
static int device_open(struct inode *inode, struct file *file)
{
printk("open the character device\n");
if(device_Open)
{
return -EBUSY;
}
device_Open++;
sprintf(msg, "I already told you %d times hello!", ++open_count);
msg_ptr = msg;
try_module_get(THIS_MODULE);
return SUCCESS;
}
static int device_release(struct inode *inode, struct file *file)
{
device_Open--;
module_put(THIS_MODULE);
return SUCCESS;
}
static ssize_t device_read(struct file *p_file, __user char *buffer,
size_t length, loff_t *offset)
{
printk("read the character device\n");
if(0 == msg_ptr)
{
return 0;
}
printk("copy string to user:%s,length:%d\n", msg_ptr, length);
return copy_to_user(buffer, msg_ptr, length);
}
static ssize_t device_write(struct file *p_file, const char *buffer,
size_t length, loff_t *offset)
{
printk("<1>SORRY, THIS OPERATION ISN'T SUPPORTED");
return -EINVAL;
}
static struct file_operations fops ={
.read = device_read,
.write = device_write,
.open = device_open,
.release = device_release
};
static int __init chrdev_init(void)
{
Major = register_chrdev(0, DEVICE_NAME, &fops);
if(Major < 0)
{
printk("<register this character device failed with %d\n", Major);
return Major;
}
printk("<1> I was assigned major number %d ",Major);
printk("<1> the drive,create a dev file");
printk("<1> mknod /dev/hello c %d 0.\n",Major);
printk("<1> I was assigned major number %d ",Major);
printk("<1> the device file\n");
printk("<1> Remove the file device and module when done\n");
return 0;
}
static void __exit chrdev_exit(void)
{
unregister_chrdev(Major, DEVICE_NAME);
printk("chardev exit\n");
}
module_init(chrdev_init);
module_exit(chrdev_exit);
/*
用户测试代码
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
int main()
{
char buff[4096] = "hello";
int fd = open("/dev/hello", O_RDWR);
int ret = read(fd, buff, sizeof(buff));
printf("%s\n", buff);
return 0;
}
内核printk的输出可以在/var/log/syslog中查看
模块代码copy_to_user的返回值为:成功:0;失败:还有多少个字节为拷贝。
里面有个小问题:当用户需要拷贝的字节数大于可以拷贝的字节数,copy_to_user如何操作的
会自动补上'\0'吗?