Linux Device Drivers 2nd Edition (779877), страница 53
Текст из файла (страница 53)
This is almost true, but not completely: small, memory-limitedsystems can still run into trouble. A driver writer ignores the possibility of allocation failures at his or her peril (or that of his or her users).Although kmalloc(GFP_KERNEL) sometimes fails when there is no availablememory, the kernel does its best to fulfill allocation requests.
Therefore, it’s easyto degrade system responsiveness by allocating too much memory. For example,you can bring the computer down by pushing too much data into a scull device;the system will start crawling while it tries to swap out as much as possible inorder to fulfill the kmalloc request. Since every resource is being sucked up by thegrowing device, the computer is soon rendered unusable; at that point you can nolonger even start a new process to try to deal with the problem. We don’t addressthis issue in scull, since it is just a sample module and not a real tool to put into amultiuser system.
As a programmer, you must nonetheless be careful, because amodule is privileged code and can open new security holes in the system (themost likely is a denial-of-service hole like the one just outlined).A scull Using Whole Pages: scullpIn order to test page allocation for real, the scullp module is released together withother sample code.
It is a reduced scull, just like scullc introduced earlier.Memory quanta allocated by scullp are whole pages or page sets: thescullp_order variable defaults to 0 and can be specified at either compile timeor load time.The following lines show how it allocates memory:/* Here’s the allocation of a single quantum */if (!dptr->data[s_pos]) {dptr->data[s_pos] =(void *)_ _get_free_pages(GFP_KERNEL, dptr->order);if (!dptr->data[s_pos])goto nomem;memset(dptr->data[s_pos], 0, PAGE_SIZE << dptr->order);}The code to deallocate memory in scullp, instead, looks like this:/* This code frees a whole quantum set */for (i = 0; i < qset; i++)if (dptr->data[i])free_pages((unsigned long)(dptr->data[i]),dptr->order);21622 June 2001 16:38http://openlib.org.uavmalloc and FriendsAt the user level, the perceived difference is primarily a speed improvement andbetter memory use because there is no internal fragmentation of memory.
We ransome tests copying four megabytes from scull0 to scull1 and then from scullp0 toscullp1; the results showed a slight improvement in kernel-space processor usage.The performance improvement is not dramatic, because kmalloc is designed to befast. The main advantage of page-level allocation isn’t actually speed, but rathermore efficient memory usage. Allocating by pages wastes no memory, whereasusing kmalloc wastes an unpredictable amount of memory because of allocationgranularity.But the biggest advantage of _ _get_fr ee_page is that the page is completely yours,and you could, in theory, assemble the pages into a linear area by appropriatetweaking of the page tables.
For example, you can allow a user process to mmapmemory areas obtained as single unrelated pages. We’ll discuss this kind of operation in ‘‘The mmap Device Operation’’ in Chapter 13, where we show how scullpoffers memory mapping, something that scull cannot offer.vmalloc and FriendsThe next memory allocation function that we’ll show you is vmalloc, which allocates a contiguous memory region in the virtual address space. Although thepages are not necessarily consecutive in physical memory (each page is retrievedwith a separate call to _ _get_fr ee_page), the kernel sees them as a contiguousrange of addresses.
vmalloc returns 0 (the NULL address) if an error occurs, otherwise, it returns a pointer to a linear memory area of size at least size.The prototypes of the function and its relatives (ior emap, which is not strictly anallocation function, will be discussed shortly) are as follows:#include <linux/vmalloc.h>voidvoidvoidvoid* vmalloc(unsigned long size);vfree(void * addr);*ioremap(unsigned long offset, unsigned long size);iounmap(void * addr);It’s worth stressing that memory addresses returned by kmalloc and get_fr ee_pagesare also virtual addresses. Their actual value is still massaged by the MMU (memory management unit, usually part of the CPU) before it is used to address physical memory.* vmalloc is not different in how it uses the hardware, but rather inhow the kernel performs the allocation task.* Actually, some architectures define ranges of ‘‘virtual’’ addresses as reserved to addressphysical memory.
When this happens, the Linux kernel takes advantage of the feature,and both the kernel and get_fr ee_pages addresses lie in one of those memory ranges. Thedifference is transparent to device drivers and other code that is not directly involvedwith the memory-management kernel subsystem.21722 June 2001 16:38http://openlib.org.uaChapter 7: Getting Hold of MemoryThe (virtual) address range used by kmalloc and get_fr ee_pages features a one-toone mapping to physical memory, possibly shifted by a constant PAGE_OFFSETvalue; the functions don’t need to modify the page tables for that address range.The address range used by vmalloc and ior emap, on the other hand, is completelysynthetic, and each allocation builds the (virtual) memory area by suitably settingup the page tables.This difference can be perceived by comparing the pointers returned by the allocation functions. On some platforms (for example, the x86), addresses returned byvmalloc are just greater than addresses that kmalloc addresses.
On other platforms(for example, MIPS and IA-64), they belong to a completely different addressrange. Addresses available for vmalloc are in the range from VMALLOC_START toVMALLOC_END. Both symbols are defined in <asm/pgtable.h>.Addresses allocated by vmalloc can’t be used outside of the microprocessor,because they make sense only on top of the processor’s MMU. When a driverneeds a real physical address (such as a DMA address, used by peripheral hardware to drive the system’s bus), you can’t easily use vmalloc.
The right time to callvmalloc is when you are allocating memory for a large sequential buffer that existsonly in software. It’s important to note that vmalloc has more overhead than_ _get_fr ee_pages because it must both retrieve the memory and build the pagetables. Therefore, it doesn’t make sense to call vmalloc to allocate just one page.An example of a function that uses vmalloc is the cr eate_module system call,which uses vmalloc to get space for the module being created.
Code and data ofthe module are later copied to the allocated space using copy_fr om_user, after insmod has relocated the code. In this way, the module appears to be loaded intocontiguous memory. You can verify, by looking in /pr oc/ksyms, that kernel symbols exported by modules lie in a different memory range than symbols exportedby the kernel proper.Memory allocated with vmalloc is released by vfr ee, in the same way that kfr eereleases memory allocated by kmalloc.Like vmalloc, ior emap builds new page tables; unlike vmalloc, however, it doesn’tactually allocate any memory. The return value of ior emap is a special virtualaddress that can be used to access the specified physical address range; the virtualaddress obtained is eventually released by calling iounmap. Note that the returnvalue from ior emap cannot be safely dereferenced on all platforms; instead, functions like readb should be used.
See “Directly Mapped Memory” in Chapter 8forthe details.ior emap is most useful for mapping the (physical) address of a PCI buffer to (virtual) kernel space. For example, it can be used to access the frame buffer of a PCIvideo device; such buffers are usually mapped at high physical addresses, outsideof the address range for which the kernel builds page tables at boot time. PCIissues are explained in more detail in “The PCI Interface” in Chapter 15.21822 June 2001 16:38http://openlib.org.uavmalloc and FriendsIt’s worth noting that for the sake of portability, you should not directly accessaddresses returned by ior emap as if they were pointers to memory. Rather, youshould always use readb and the other I/O functions introduced in Using I/OMemory, in Chapter 8.
This requirement applies because some platforms, such asthe Alpha, are unable to directly map PCI memory regions to the processoraddress space because of differences between PCI specs and Alpha processors inhow data is transferred.There is almost no limit to how much memory vmalloc can allocate and ior emapcan make accessible, although vmalloc refuses to allocate more memory than theamount of physical RAM, in order to detect common errors or typos made by programmers. You should remember, however, that requesting too much memorywith vmalloc leads to the same problems as it does with kmalloc.Both ior emap and vmalloc are page oriented (they work by modifying the pagetables); thus the relocated or allocated size is rounded up to the nearest pageboundary.