📄 mmap.html
字号:
*/</span><span class="kw4">static</span> <span class="kw4">int</span> simple_release<span class="br0">(</span><span class="kw4">struct</span> inode *inode, <span class="kw4">struct</span> file *filp<span class="br0">)</span><span class="br0">{</span> <span class="kw1">return</span> <span class="nu0">0</span>;<span class="br0">}</span> <span class="coMULTI">/* * Common VMA ops. */</span> <span class="kw4">void</span> simple_vma_open<span class="br0">(</span><span class="kw4">struct</span> vm_area_struct *vma<span class="br0">)</span><span class="br0">{</span> printk<span class="br0">(</span><span class="st0">"Simple VMA open, virt %lx, phys %lx<span class="es0">\n</span>"</span>, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT<span class="br0">)</span>;<span class="br0">}</span> <span class="kw4">void</span> simple_vma_close<span class="br0">(</span><span class="kw4">struct</span> vm_area_struct *vma<span class="br0">)</span><span class="br0">{</span> printk<span class="br0">(</span><span class="st0">"Simple VMA close.<span class="es0">\n</span>"</span><span class="br0">)</span>;<span class="br0">}</span> <span class="coMULTI">/* * The remap_pfn_range version of mmap. This one is heavily borrowed * from drivers/char/mem.c. */</span> <span class="kw4">static</span> <span class="kw4">struct</span> vm_operations_struct simple_remap_vm_ops = <span class="br0">{</span> .<span class="me1">open</span> = simple_vma_open, .<span class="me1">close</span> = simple_vma_close,<span class="br0">}</span>; <span class="kw4">static</span> <span class="kw4">int</span> simple_remap_mmap<span class="br0">(</span><span class="kw4">struct</span> file *filp, <span class="kw4">struct</span> vm_area_struct *vma<span class="br0">)</span><span class="br0">{</span> <span class="coMULTI">/* In this sample we are using _ramend -> physical_mem_end as the buffer to be mmaped. */</span> <span class="kw2">extern</span> <span class="kw4">unsigned</span> <span class="kw4">long</span> physical_mem_end; <span class="kw2">extern</span> <span class="kw4">int</span> _ramend; <span class="coMULTI">/* the kernel passes in the vm_pgoff - the offset, in *pages* * from the start of the buffer that the user space app wants * to mmap. This is the last arg in the user space mmap call. * We check it to make sure it is not out of bounds. */</span> <span class="kw1">if</span> <span class="br0">(</span>vma->vm_pgoff > <span class="br0">(</span><span class="br0">(</span>physical_mem_end - _ramend<span class="br0">)</span> >> PAGE_SHIFT<span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw1">return</span> -EINVAL; <span class="br0">}</span> vma->vm_start = <span class="br0">(</span><span class="kw4">unsigned</span> <span class="kw4">long</span><span class="br0">)</span>_ramend; vma->vm_end = <span class="br0">(</span><span class="kw4">unsigned</span> <span class="kw4">long</span><span class="br0">)</span>physical_mem_end; <span class="coMULTI">/* before remap is called, pgoff must be set to the kernel page * offset from zero. Do to this, we figure out the address, * ( << PAGE_SHIFT ), add it to the start of the buffer, and * turn that back to pages (>> PAGE_SHIFT) */</span> vma->vm_pgoff = <span class="br0">(</span><span class="br0">(</span>vma->vm_pgoff << PAGE_SHIFT <span class="br0">)</span> + <span class="br0">(</span><span class="kw4">unsigned</span> <span class="kw4">long</span><span class="br0">)</span>_ramend <span class="br0">)</span> >> PAGE_SHIFT; <span class="coMULTI">/* VM_MAYSHARE limits for mprotect(), and must be set on nommu. * Other flags can be set, and are documented in * include/linux/mm.h */</span> vma->vm_flags |= VM_MAYSHARE; <span class="kw1">if</span> <span class="br0">(</span>remap_pfn_range<span class="br0">(</span>vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot<span class="br0">)</span><span class="br0">)</span> <span class="kw1">return</span> -EAGAIN; vma->vm_ops = &simple_remap_vm_ops; simple_vma_open<span class="br0">(</span>vma<span class="br0">)</span>; <span class="kw1">return</span> <span class="nu0">0</span>;<span class="br0">}</span> ssize_t simple_read <span class="br0">(</span><span class="kw4">struct</span> file *filp, <span class="kw4">char</span> __user *buf, size_t count, loff_t *f_pos<span class="br0">)</span><span class="br0">{</span> <span class="kw1">return</span> count;<span class="br0">}</span> <span class="coMULTI">/* * Set up the cdev structure for a device. */</span><span class="kw4">static</span> <span class="kw4">void</span> simple_setup_cdev<span class="br0">(</span><span class="kw4">struct</span> cdev *dev, <span class="kw4">int</span> minor, <span class="kw4">struct</span> file_operations *fops<span class="br0">)</span><span class="br0">{</span> <span class="kw4">int</span> err, devno = MKDEV<span class="br0">(</span>simple_major, minor<span class="br0">)</span>; cdev_init<span class="br0">(</span>dev, fops<span class="br0">)</span>; dev->owner = THIS_MODULE; dev->ops = fops; err = cdev_add <span class="br0">(</span>dev, devno, <span class="nu0">1</span><span class="br0">)</span>; <span class="coMULTI">/* Fail gracefully if need be */</span> <span class="kw1">if</span> <span class="br0">(</span>err<span class="br0">)</span> printk <span class="br0">(</span>KERN_NOTICE <span class="st0">"Error %d adding simple%d"</span>, err, minor<span class="br0">)</span>;<span class="br0">}</span> <span class="coMULTI">/* * Our various sub-devices. */</span><span class="coMULTI">/* Device 0 uses remap_pfn_range */</span><span class="kw4">static</span> <span class="kw4">struct</span> file_operations simple_remap_ops = <span class="br0">{</span> .<span class="me1">owner</span> = THIS_MODULE, .<span class="me1">open</span> = simple_open, .<span class="me1">read</span> = simple_read, .<span class="me1">release</span> = simple_release, .<span class="me1">mmap</span> = simple_remap_mmap,<span class="br0">}</span>; <span class="co2">#define MAX_SIMPLE_DEV 1</span> <span class="coMULTI">/* * We export two simple devices. There's no need for us to maintain any * special housekeeping info, so we just deal with raw cdevs. */</span><span class="kw4">static</span> <span class="kw4">struct</span> cdev SimpleDevs<span class="br0">[</span>MAX_SIMPLE_DEV<span class="br0">]</span>; <span class="coMULTI">/* * Module housekeeping. */</span><span class="kw4">static</span> <span class="kw4">int</span> simple_init<span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span><span class="br0">{</span> <span class="kw4">int</span> result; dev_t dev = MKDEV<span class="br0">(</span>simple_major, <span class="nu0">0</span><span class="br0">)</span>; <span class="coMULTI">/* Figure out our device number. */</span> <span class="kw1">if</span> <span class="br0">(</span>simple_major<span class="br0">)</span> result = register_chrdev_region<span class="br0">(</span>dev, <span class="nu0">2</span>, <span class="st0">"simple"</span><span class="br0">)</span>; <span class="kw1">else</span> <span class="br0">{</span> result = alloc_chrdev_region<span class="br0">(</span>&dev, <span class="nu0">0</span>, <span class="nu0">2</span>, <span class="st0">"simple"</span><span class="br0">)</span>; simple_major = MAJOR<span class="br0">(</span>dev<span class="br0">)</span>; <span class="br0">}</span> <span class="kw1">if</span> <span class="br0">(</span>result < <span class="nu0">0</span><span class="br0">)</span> <span class="br0">{</span> printk<span class="br0">(</span>KERN_WARNING <span class="st0">"simple: unable to get major %d<span class="es0">\n</span>"</span>, simple_major<span class="br0">)</span>; <span class="kw1">return</span> result; <span class="br0">}</span> <span class="kw1">if</span> <span class="br0">(</span>simple_major == <span class="nu0">0</span><span class="br0">)</span> simple_major = result; <span class="coMULTI">/* Now set up two cdevs. */</span> simple_setup_cdev<span class="br0">(</span>SimpleDevs, <span class="nu0">0</span>, &simple_remap_ops<span class="br0">)</span>; <span class="kw1">return</span> <span class="nu0">0</span>;<span class="br0">}</span> <span class="kw4">static</span> <span class="kw4">void</span> simple_cleanup<span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span><span class="br0">{</span> cdev_del<span class="br0">(</span>SimpleDevs<span class="br0">)</span>; unregister_chrdev_region<span class="br0">(</span>MKDEV<span class="br0">(</span>simple_major, <span class="nu0">0</span><span class="br0">)</span>, <span class="nu0">2</span><span class="br0">)</span>;<span class="br0">}</span> module_init<span class="br0">(</span>simple_init<span class="br0">)</span>;module_exit<span class="br0">(</span>simple_cleanup<span class="br0">)</span>;</pre><p> And use “mknod simple c 254 0” to create the “/dev/simple” device for applications to open. </p></div><h4><a name="mmap_user_code" id="mmap_user_code">MMAP User code</a></h4><div class="level4"><p> A typical user code example is shown</p><p>The pointer returned by the <strong>mmap</strong> function can be used as normal read / write memory </p><pre class="code c"> <span class="co1">// bfin-uclinux-gcc -Wl,-elf2flt -o test_simple test_simple.c</span><span class="co2">#include <fcntl.h></span><span class="co2">#include <unistd.h></span><span class="co2">#include <sys/types.h></span><span class="co2">#include <sys/mman.h></span> <span class="co2">#define SIMPLE_DEVICE "/dev/simple"</span> <span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span> <span class="kw4">int</span> i; <span class="kw4">int</span> fd; <span class="kw4">char</span> * p; fd = open<span class="br0">(</span>SIMPLE_DEVICE,O_RDWR<span class="br0">)</span>; <span class="kw1">if</span> <span class="br0">(</span> fd < <span class="nu0">0</span> <span class="br0">)</span> <span class="br0">{</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">(</span><span class="st0">"error in device <span class="es0">\n</span>"</span><span class="br0">)</span>; exit<span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span>; <span class="br0">}</span> p = <span class="br0">(</span> <span class="kw4">char</span> *<span class="br0">)</span> mmap<span class="br0">(</span><span class="kw2">NULL</span>, <span class="nu0">1024</span>, PROT_READ, MAP_PRIVATE,fd,0x1000<span class="br0">)</span>; <span class="kw1">if</span> <span class="br0">(</span> p == MAP_FAILED <span class="br0">)</span> <span class="br0">{</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">(</span><span class="st0">" failed to mmap device <span class="es0">\n</span>"</span><span class="br0">)</span>; exit<span class="br0">(</span><span class="nu0">1</span><span class="br0">)</span>; <span class="br0">}</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">(</span><span class="st0">" mmap device ok p = %p<span class="es0">\n</span>"</span>,p<span class="br0">)</span>; <span class="kw1">for</span> <span class="br0">(</span>i = <span class="nu0">0</span>; i < <span class="nu0">1024</span>; i++<span class="br0">)</span> *<span class="br0">(</span>p + i<span class="br0">)</span> = 0x55; <span class="kw1">for</span> <span class="br0">(</span>i = <span class="nu0">0</span>; i < <span class="nu0">1024</span>; i++<span class="br0">)</span> <span class="br0">{</span> <span class="kw1">if</span> <span class="br0">(</span>*<span class="br0">(</span>p + i<span class="br0">)</span> != 0x55<span class="br0">)</span> <span class="br0">{</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">(</span><span class="st0">" memory write/read error! <span class="es0">\n</span>"</span><span class="br0">)</span>; <span class="kw1">return</span> <span class="nu0">-1</span>; <span class="br0">}</span> <span class="br0">}</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/printf.html"><span class="kw3">printf</span></a><span class="br0">(</span><span class="st0">" memory write/read succeed<span class="es0">\n</span>"</span><span class="br0">)</span>; close<span class="br0">(</span>fd<span class="br0">)</span>; <span class="kw1">return</span> <span class="nu0">0</span>;<span class="br0">}</span></pre></div><!-- SECTION [6326-] --></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -