📄 hello.c
字号:
#ifndef MODULE#define MODULE#endif //MODULE#ifndef __KERNEL__#define __KERNEL__#endif //__KERNEL__#ifndef LINUX#define LINUX#endif //LINUX#ifndef __LINUX__#define __LINUX__#endif //__LINUX__#include <linux/config.h>#include <linux/module.h>#include <linux/init.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/errno.h>#include <linux/kdev_t.h>//#include <linux/sched.h>#include <linux/cdev.h>#include <asm/uaccess.h>#include "hello.h"MODULE_LICENSE("GPL");MODULE_AUTHOR("WangQiang");#define DATA_BUFFER_SIZE 4096#define DRIVER_NAME "my_device"static char *g_pData = 0;static dev_t g_devno = 0;static struct cdev g_dev;//wrapper "read" functionstatic int my_read( struct file *filp, char *charp, size_t iLen, loff_t *pPos){ printk("my driver read.\n"); if(g_pData == 0) { return -ENOMEM; } printk("process %d (%s) readding...\n", current->pid, current->comm); size_t iRealLen = iLen>DATA_BUFFER_SIZE?DATA_BUFFER_SIZE:iLen; return iLen-copy_to_user(charp, g_pData, iRealLen);}//wrapper "write" functionstatic int my_write( struct file *filp, const char *charp, size_t iLen, loff_t *pPos){ printk("my driver write.\n"); if(g_pData == 0) { return -ENOMEM; } printk("process %d (%s) writting...\n", current->pid, current->comm); size_t iRealLen = iLen>DATA_BUFFER_SIZE?DATA_BUFFER_SIZE:iLen; return iLen-copy_from_user(g_pData, charp, iRealLen);}//wrapper "open" functionstatic int my_open( struct inode *pinode, struct file *filp){ printk("process %d (%s) open my device.\n", current->pid, current->comm); return 0;}//wrapper "release" functionstatic int my_release( struct inode *pinode, struct file *filp){ printk("process %d (%s) close my device.\n", current->pid, current->comm); return 0;}//wrapper "ioctl" functionstatic int my_ioctl( struct inode *pinode, struct file *pFile, unsigned int uiCmd, unsigned long ulPara){ int iRet = -EINVAL;//NOTTY; switch(uiCmd) { case HELLO_IOGBUFFERSIZE: { iRet = DATA_BUFFER_SIZE; printk("receive \"IOGBUFFERSIZE\" ioctl command, return DATA_BUFFER_SIZE.\n"); } break; case HELLO_IOGBUFFERSIZE2: { if(access_ok(VERIFY_WRITE, (void __user*)ulPara, _IOC_SIZE(uiCmd)) == 1) { __put_user(DATA_BUFFER_SIZE, (int __user*)ulPara); iRet = 0; } else { iRet = -EINVAL; } } break; default:; } return iRet;}//register callback functionstatic struct file_operations my_fops = { .owner = THIS_MODULE, .open = my_open, .release = my_release, .read = my_read, .write = my_write, .ioctl = my_ioctl,};//driver initial functionstatic int __init my_init(void){ printk("Hello! My friend! this is my first driver in linux.\n"); g_pData = (char*)kmalloc(DATA_BUFFER_SIZE, GFP_ATOMIC); if(g_pData == 0) { return -ENOMEM; } //get device no if(alloc_chrdev_region(&g_devno, 0, 1, DRIVER_NAME) == 0) { int iErr = 0; printk("system alloc \"%s\" major:%d, minor:%d\n", DRIVER_NAME, MAJOR(g_devno), MINOR(g_devno)); //register my device cdev_init(&g_dev, &my_fops); g_dev.owner = THIS_MODULE; g_dev.ops = &my_fops; iErr = cdev_add(&g_dev, g_devno, 1); if(iErr != 0) { printk("register my device failure.\n"); kfree(g_pData); g_pData = 0; return -1; } } else { printk("system alloc \"%s\" major and minor failure.\n", DRIVER_NAME); return 1; } return 0;}//driver uninitital functionstatic void __exit my_cleanup(void){ printk("Goodbye my friend! my first driver exit.\n"); cdev_del(&g_dev); unregister_chrdev_region(g_devno, 1); kfree(g_pData); g_pData = 0;}//register driver initial functionmodule_init(my_init);//register driver uninitital functionmodule_exit(my_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -