-Linux character driver example on 3.19.0-43-generic -
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #ifndef __KERNEL__ #define __KERNEL__ #endif #ifndef MODULE #define MODULE #endif #include <linux/slab.h> #include <linux/device.h> #include <linux/proc_fs.h> #include <asm/uaccess.h> static DEFINE_MUTEX(mutexIoctl); //Mutex for unlocked_ioctl static unsigned char* chpBuf = NULL; //Device buffer pointer static int memOpen(struct inode *inp, struct file *fp); static int memRel(struct inode *inp, struct file *fp); static ssize_t memRead(struct file *fp, unsigned char *chpOut, size_t sztCount, loff_t *loftPos); static ssize_t memWrite(struct file *fp, const unsigned char __user *chpIn, size_t sztCount, loff_t *loftPos); static long memIoctl(struct file *fp, unsigned int iNum, unsigned long iParam); //Device callback functions static struct file_operations fileOpers; static bool bFlag = false; //Custom device mutex static int __init kernmodule_init(void) { void *vpErr; //Error pointer fileOpers.read = memRead; fileOpers.write = memWrite; fileOpers.open = memOpen; fileOpers.release = memRel; fileOpers.unlocked_ioctl = memIoctl; //Allocate callback functions if(register_chrdev(200, "kernmodule", &fileOpers) < 0) return -EIO; //Register character device (major = 200, device name = kernmodule) chpBuf = kmalloc(32, GFP_USER); if(IS_ERR(vpErr = chpBuf)) return -ENOMEM; memset(chpBuf, 0, 32); //Allocate memory area for device buffer } static void __exit kernmodule_exit(void) { unregister_chrdev(200, "kernmodule"); //Unregister character device if(chpBuf) kfree(chpBuf); } static int memOpen(struct inode *inp, struct file *fp){ //Device file open if(bFlag) return -EBUSY; bFlag = true; return 0; } static int memRel(struct inode *inp, struct file *fp){ //Device file release bFlag = false; return 0; } static ssize_t memRead(struct file *fp, unsigned char __user *chpOut, size_t sztCount, loff_t *loftPos){ //read() from device file if(sztCount > 32) return -1; if(bFlag) copy_to_user(chpOut, chpBuf, sztCount); return sztCount; } static ssize_t memWrite(struct file *fp, const unsigned char __user *chpIn, size_t sztCount, loff_t *loftPos){ //write() to device file if(sztCount > 32) return -1; if(bFlag) copy_from_user(chpBuf, chpIn, sztCount); return sztCount; } static long memIoctl(struct file *fp, unsigned int uiNum, unsigned long ulParam) { int iIter = 0; mutex_lock(&mutexIoctl); //ioctl Routine(User-level application can access with ioctl() function) mutex_unlock(&mutexIoctl); return 0; } //unlocked_ioctl : normal ioctl was deprecated module_init(kernmodule_init); module_exit(kernmodule_exit); | cs |
'Linux Kernel, System' 카테고리의 다른 글
[Linux/Kernel] Kernel readv/writev implementation (1) (0) | 2016.09.11 |
---|---|
[Linux/Kernel] Kernel 4.6.3 new read() implementation (0) | 2016.07.02 |
[Linux/Kernel] Linux Kernel 4.6.3 Ethernet - eth_header() (0) | 2016.06.28 |
[Linux/System] Allocate Space in the Stack (0) | 2016.04.25 |
[Linux/System] Anonymous Memory Mapping (0) | 2016.04.25 |