|
3 | 3 | #include <linux/init.h> |
4 | 4 | #include <linux/fs.h> |
5 | 5 | #include <linux/debugfs.h> |
| 6 | +#include <linux/slab.h> |
6 | 7 |
|
7 | 8 | #include <linux/mm.h> /* mmap related stuff */ |
8 | 9 |
|
9 | | -struct dentry *file1; |
| 10 | +#define NOPAGE_SIGBUS (NULL) |
| 11 | + |
| 12 | +struct dentry* file1; |
10 | 13 |
|
11 | 14 | struct mmap_info { |
12 | | - char *data; /* the data */ |
13 | | - int reference; /* how many times it is mmapped */ |
| 15 | + char* data; /* the data */ |
| 16 | + int reference; /* how many times it is mmapped */ |
14 | 17 | }; |
15 | 18 |
|
16 | 19 |
|
17 | 20 | /* keep track of how many times it is mmapped */ |
18 | 21 |
|
19 | | -void mmap_open(struct vm_area_struct *vma) |
| 22 | +void mmap_open(struct vm_area_struct* vma) |
20 | 23 | { |
21 | | - struct mmap_info *info = (struct mmap_info *)vma->vm_private_data; |
22 | | - info->reference++; |
| 24 | + struct mmap_info* info = (struct mmap_info*)vma->vm_private_data; |
| 25 | + info->reference++; |
23 | 26 | } |
24 | 27 |
|
25 | | -void mmap_close(struct vm_area_struct *vma) |
| 28 | +void mmap_close(struct vm_area_struct* vma) |
26 | 29 | { |
27 | | - struct mmap_info *info = (struct mmap_info *)vma->vm_private_data; |
28 | | - info->reference--; |
| 30 | + struct mmap_info* info = (struct mmap_info*)vma->vm_private_data; |
| 31 | + info->reference--; |
29 | 32 | } |
30 | 33 |
|
31 | 34 | /* nopage is called the first time a memory area is accessed which is not in memory, |
32 | 35 | * it does the actual mapping between kernel and user space memory |
33 | 36 | */ |
34 | | -struct page *mmap_nopage(struct vm_area_struct *vma, unsigned long address, int *type) |
| 37 | +struct page* mmap_nopage(struct vm_area_struct* vma, unsigned long address, |
| 38 | + int* type) |
35 | 39 | { |
36 | | - struct page *page; |
37 | | - struct mmap_info *info; |
38 | | - /* is the address valid? */ |
39 | | - if (address > vma->vm_end) { |
40 | | - printk("invalid address\n"); |
41 | | - return NOPAGE_SIGBUS; |
42 | | - } |
43 | | - /* the data is in vma->vm_private_data */ |
44 | | - info = (struct mmap_info *)vma->vm_private_data; |
45 | | - if (!info->data) { |
46 | | - printk("no data\n"); |
47 | | - return NULL; |
48 | | - } |
49 | | - |
50 | | - /* get the page */ |
51 | | - page = virt_to_page(info->data); |
52 | | - |
53 | | - /* increment the reference count of this page */ |
54 | | - get_page(page); |
55 | | - /* type is the page fault type */ |
56 | | - if (type) |
57 | | - *type = VM_FAULT_MINOR; |
58 | | - |
59 | | - return page; |
| 40 | + struct page* page; |
| 41 | + struct mmap_info* info; |
| 42 | + |
| 43 | + /* is the address valid? */ |
| 44 | + if (address > vma->vm_end) { |
| 45 | + printk("invalid address\n"); |
| 46 | + return NOPAGE_SIGBUS; |
| 47 | + } |
| 48 | + |
| 49 | + /* the data is in vma->vm_private_data */ |
| 50 | + info = (struct mmap_info*)vma->vm_private_data; |
| 51 | + |
| 52 | + if (!info->data) { |
| 53 | + printk("no data\n"); |
| 54 | + return NULL; |
| 55 | + } |
| 56 | + |
| 57 | + /* get the page */ |
| 58 | + page = virt_to_page(info->data); |
| 59 | + |
| 60 | + /* increment the reference count of this page */ |
| 61 | + get_page(page); |
| 62 | + |
| 63 | + /* type is the page fault type */ |
| 64 | + if (type) { |
| 65 | + *type = VM_FAULT_MINOR; |
| 66 | + } |
| 67 | + |
| 68 | + return page; |
60 | 69 | } |
61 | 70 |
|
62 | 71 | struct vm_operations_struct mmap_vm_ops = { |
63 | | - .open = mmap_open, |
64 | | - .close = mmap_close, |
65 | | - .nopage = mmap_nopage, |
| 72 | + .open = mmap_open, |
| 73 | + .close = mmap_close, |
| 74 | + //.nopage = mmap_nopage, |
66 | 75 | }; |
67 | 76 |
|
68 | | -int my_mmap(struct file *filp, struct vm_area_struct *vma) |
| 77 | +int my_mmap(struct file* filp, struct vm_area_struct* vma) |
69 | 78 | { |
70 | | - vma->vm_ops = &mmap_vm_ops; |
71 | | - vma->vm_flags |= VM_RESERVED; |
72 | | - /* assign the file private data to the vm private data */ |
73 | | - vma->vm_private_data = filp->private_data; |
74 | | - mmap_open(vma); |
75 | | - return 0; |
| 79 | + vma->vm_ops = &mmap_vm_ops; |
| 80 | + vma->vm_flags |= (VM_DONTEXPAND | VM_DONTDUMP); |
| 81 | + /* assign the file private data to the vm private data */ |
| 82 | + vma->vm_private_data = filp->private_data; |
| 83 | + mmap_open(vma); |
| 84 | + return 0; |
76 | 85 | } |
77 | 86 |
|
78 | | -int my_close(struct inode *inode, struct file *filp) |
| 87 | +int my_close(struct inode* inode, struct file* filp) |
79 | 88 | { |
80 | | - struct mmap_info *info = filp->private_data; |
81 | | - /* obtain new memory */ |
82 | | - free_page((unsigned long)info->data); |
83 | | - kfree(info); |
84 | | - filp->private_data = NULL; |
85 | | - return 0; |
| 89 | + struct mmap_info* info = filp->private_data; |
| 90 | + /* obtain new memory */ |
| 91 | + free_page((unsigned long)info->data); |
| 92 | + kfree(info); |
| 93 | + filp->private_data = NULL; |
| 94 | + return 0; |
86 | 95 | } |
87 | 96 |
|
88 | | -int my_open(struct inode *inode, struct file *filp) |
| 97 | +int my_open(struct inode* inode, struct file* filp) |
89 | 98 | { |
90 | | - struct mmap_info *info = kmalloc(sizeof(struct mmap_info), GFP_KERNEL); |
91 | | - /* obtain new memory */ |
92 | | - info->data = (char *)get_zeroed_page(GFP_KERNEL); |
93 | | - memcpy(info->data, "hello from kernel this is file: ", 32); |
94 | | - memcpy(info->data + 32, filp->f_dentry->d_name.name, strlen(filp->f_dentry->d_name.name)); |
95 | | - /* assign this info struct to the file */ |
96 | | - filp->private_data = info; |
97 | | - return 0; |
| 99 | + struct mmap_info* info = kmalloc(sizeof(struct mmap_info), GFP_KERNEL); |
| 100 | + /* obtain new memory */ |
| 101 | + info->data = (char*)get_zeroed_page(GFP_KERNEL); |
| 102 | + memcpy(info->data, "hello from kernel this is file: ", 32); |
| 103 | + memcpy(info->data + 32, filp->f_path.dentry->d_name.name, |
| 104 | + strlen(filp->f_path.dentry->d_name.name)); |
| 105 | + /* assign this info struct to the file */ |
| 106 | + filp->private_data = info; |
| 107 | + return 0; |
98 | 108 | } |
99 | 109 |
|
100 | 110 | static const struct file_operations my_fops = { |
101 | | - .open = my_open, |
102 | | - .release = my_close, |
103 | | - .mmap = my_mmap, |
| 111 | + .open = my_open, |
| 112 | + .release = my_close, |
| 113 | + .mmap = my_mmap, |
104 | 114 | }; |
105 | 115 |
|
106 | 116 | static int __init mmapexample_module_init(void) |
107 | 117 | { |
108 | | - file1 = debugfs_create_file("mmap_example", 0644, NULL, NULL, &my_fops); |
109 | | - return 0; |
| 118 | + printk("mmapexample_module_init\n"); |
| 119 | + file1 = debugfs_create_file("mmap_example", 0644, NULL, NULL, &my_fops); |
| 120 | + return 0; |
110 | 121 | } |
111 | 122 |
|
112 | 123 | static void __exit mmapexample_module_exit(void) |
113 | 124 | { |
114 | | - debugfs_remove(file1); |
115 | | - |
| 125 | + printk("mmapexample_module_exit\n"); |
| 126 | + debugfs_remove(file1); |
116 | 127 | } |
117 | 128 |
|
118 | 129 | module_init(mmapexample_module_init); |
|
0 commit comments