Monday, June 27, 2011

Adding a Linux device driver for Target Board

Adding a Linux device driver

On Linux systems, device drivers are typically distributed in one of three forms:

* A patch against a specific kernel version
* A loadable module
* An installation script that applies appropriate patches

The most common of all these is the patch against a specific kernel version. These patches can in most cases be applied with the following procedure:2

# cd /usr/src/linux ; patch -p1 < patch_file Diffs made against a different minor version of the kernel may fail, but the driver should still work. Here, we cover how to manually add a network "snarf" driver to the kernel. It's a very complicated and tedious process, especially when compared to other operating systems we've seen. By convention, Linux kernel source resides in /usr/src/linux. Within the drivers subdirectory, you'll need to find the subdirectory that corresponds to the type of device you have. A directory listing of drivers looks like this: % ls -F /usr/src/linux/drivers Makefile cdrom/ i2o/ nubus/ sbus/ telephony/ acorn/ char/ isdn/ parport/ scsi/ usb/ ap1000/ dio/ macintosh/ pci/ sgi/ video/ atm/ fc4/ misc/ pcmcia/ sound/ zorro/ block/ i2c/ net/ pnp/ tc/ The most common directories to which drivers are added are block, char, net, usb, sound, and scsi. These directories contain drivers for block devices (such as IDE disk drives), character devices (such as serial ports), network devices, USB devices, sound cards, and SCSI cards, respectively. Some of the other directories contain drivers for the buses themselves (e.g., pci, nubus, and zorro); it's unlikely that you will need to add drivers to these directories. Some directories contain platform-specific drivers, such as macintosh, acorn, and ap1000. Some directories contain specialty devices such as atm, isdn, and telephony. Since our example device is a network-related device, we will add the driver to the directory drivers/net. We'll need to modify the following files: * drivers/net/Makefile, so that our driver will be compiled * drivers/net/Config.in, so that our device will appear in the config options * drivers/net/Space.c, so that the device will be probed on startup After putting the .c and .h files for the driver in drivers/net, we'll add the driver to drivers/net/Makefile. The lines we'd add (near the end of the file) follow. ifeq ($(CONFIG_SNARF),y) L_OBJS += snarf.o else ifeq ($(CONFIG_SNARF),m) M_OBJS += snarf.o endif endif This configuration adds the snarf driver so that it can be either configured as a module or built into the kernel. After adding the device to the Makefile, we have to make sure we can configure the device when we configure the kernel. All network devices need to be listed in the file drivers/net/Config.in. To add the device so that it can be built either as a module or as part of the kernel (consistent with what we claimed in the Makefile), we add the following line: tristate 'Snarf device support' CONFIG_SNARF The tristate keyword means you can build the device as a module. If the device cannot be built as a module, use the keyword bool instead of tristate. The next token is the string to display on the configuration screen. It can be any arbitrary text, but it should identify the device that is being configured. The final token is the configuration macro. This token needs to be the same as that tested for with the ifeq clause in the Makefile. The last file we need to edit to add our device to the system is drivers/net/Space.c. Space.c contains references to the probe routines for the device driver, and it also controls the device probe order. Here, we'll have to edit the file in two different places. First we'll add a reference to the probe function, then we'll add the device to the list of devices to probe for. At the top of the Space.c file are a bunch of references to other probe functions. We'll add the following line to that list: extern int snarf_probe(struct device *); Next, to add the device to the actual probe list, we need to determine which list to add it to. A separate probe list is kept for each type of bus (PCI, EISA, SBus, MCA, ISA, parallel port, etc.). The snarf device is a PCI device, so we'll add it to the list called pci_probes. The line that says struct devprobe pci_probes[] __initdata = { is followed by an ordered list of devices. The devices higher up in the list are probed first. Probe order does not usually matter for PCI devices, but some devices are sensitive. Just to be sure the snarf device is detected, we'll add it to the top of the list: struct devprobe pci_probes[] __initdata = { #ifdef CONFIG_SNARF snarf_probe, 0}, #endif The device has now been added to the Linux kernel. When we next configure the kernel, the device should appear as a configuration option under "network devices." Adding new kernel module to linux source tree Posted on October 24, 2010 by Ravi Teja G Kernel modules in linux are important programs that can be loaded and unloaded at wish without having to compile them into linux kernel image itself. All the device drivers are written using these loadable modules. Let us add a very basic sample kernel module. Add this file to drivers/misc directory in linux kernel source. drivers/misc/hello_world.c view source print? 01 #include
02 #include
03
04 static int __init hello_world_module_init(void)
05 {
06 printk("Hello World, sample module is installed!\n");
07 return 0;
08 }
09
10 static void __exit hello_world_module_cleanup(void)
11 {
12 printk("Good-bye, sample module was removed!\n");
13 }
14
15 module_init(hello_world_module_init);
16 module_exit(hello_world_module_cleanup);
17 MODULE_LICENSE("GPL");

Next we have to add configuration settings, so that our module can be enabled or disabled. Add these lines to drivers/misc/Kconfig file,
view source
print?
1 config HELLO_WORLD_MODULE
2 tristate "hello world module"
3 depends on ARM
4 default m if ARM
5 help
6 hello world module.

Line 3 states that this option can only be enabled if CONFIG_ARM is enabled and Line 4 states that this option should be enabled as default when CONFIG_ARM is enabled. Next We have to inform kernel to compile hello_world.c when HELLO_WORLD_MODULE configuration is enabled. Add this line to drivers/misc/Makefile,
view source
print?
1 obj-$(CONFIG_HELLO_WORLD_MODULE)+= hello_world.o

We have successfully added a new module to linux kernel. Now let us compile and test our new module. We have to start from “make defconfig” so that our changes to configuration files take effect.

$ export CROSS_COMPILE=arm-none-linux-gnueabi-
$ export ARCH=arm
$ make clean
$ make mini2440_defconfig
$ make menuconfig

Enable our newly added module from Device Drivers —> Misc devices —> hello world module. Now start compiling modules.

$ make modules
$ make modules_install INSTALL_MOD_PATH=$ROOTFS

Here $ROOTFS is the target file system. Now to test our new module,

$ modprobe hello_world
Hello World, sample module is installed !
$ rmmod hello_world
Good-bye, sample module was removed!

U-boot_config_src

Das U-Boot
==> Unpacking the Source Code:
If you used GIT to get a copy of the U-Boot sources, then you can skip this next step since you already have
an unpacked directory tree. If you downloaded a compressed tarball from the DENX FTP server, you can
unpack it as follows:
$ cd /opt/eldk/usr/src
$ wget ftp://ftp.denx.de/pub/u-boot/u-boot-1.3.2.tar.bz2
$ rm -f u-boot
$ bunzip2 < u-boot-1.3.2.tar.bz2 | tar xf - $ ln -s u-boot-1.3.2 u-boot $ cd u-boot ==> Configuration:
After changing to the directory with the U-Boot source code you should make sure that there are no build
results from any previous configurations left:
$ make distclean
The following (model) command configures U-Boot for the canyonlands board:
$ make canyonlands_config
And finally we can compile the tools and U-Boot itself:
$ make all
By default the build is performed locally and the objects are saved in the source directory. One of the two
methods can be used to change this behaviour and build U-Boot to some external directory:
1. Add O= to the make command line invocations:
make O=/tmp/build distclean
make O=/tmp/build canyonlands_config
make O=/tmp/build all
Note that if the 'O=output/dir' option is used then it must be used for all invocations of make.
2. Set environment variable BUILD_DIR to point to the desired location:
export BUILD_DIR=/tmp/build
make distclean
make canyonlands_config
make all
Note that the command line "O=" setting overrides the BUILD_DIR environment variable.

Kernel Configuration and Compilation

Embedded Linux Configuration
===>> Download and Unpack the Linux Kernel Sources


>> To be sure that no intermediate results of previous builds are left in your Linux kernel source tree you can
clean it up as follows:

-- bash# make mrproper

>> The following command selects a standard configuration for the canyonlands board that has been extensively
tested. It is recommended to use this as a starting point for other, customized configurations:

-- bash# make ARCH=powerpc CROSS_COMPILE=ppc_4xx- canyonlands_defconfig

Note: The name of this default configuration file is arch/powerpc/configs/XXX_defconfig . By
listing the contents of the arch/powerpc/configs/ directory you can easily find out which other default
configurations are available.

>> If you don't want to change the default configuration you can now continue to use it to build a kernel image:

-- bash# make ARCH=powerpc CROSS_COMPILE=ppc_4xx- uImage
-- bash# cp arch/powerpc/boot/uImage /tftpboot

>> Otherwise you can modify the kernel configuration as follows:
-- bash$ make ARCH=powerpc CROSS_COMPILE=ppc_4xx- config
OR
-- bash$ make ARCH=powerpc CROSS_COMPILE=ppc_4xx- menuconfig
Note: Because of problems (especially with some older Linux kernel versions) the use of "make xconfig"
is not recommended.

-- bash$ make ARCH=powerpc CROSS_COMPILE=ppc_4xx- uImage

The make target uImage uses the tool mkimage (from the U-Boot package) to create a Linux kernel image in
arch/powerpc/boot/uImage


which is immediately usable for download and booting with U-Boot.

In case you configured modules you will also need to compile the modules:

-- make ARCH=powerpc CROSS_COMPILE=ppc_4xx- modules

add install the modules (make sure to pass the correct root path for module installation):

-- bash$ make ARCH=powerpc CROSS_COMPILE=ppc_4xx- INSTALL_MOD_PATH=/opt/eldk-4.2/ppc_4xx modules_ins

Friday, June 24, 2011

How to remove duplicate entries in a file without sorting

GNU awk is a programming language that is designed for processing text-based data, either in files or data streams, and was created in the 1970s at Bell Labs.

To remove duplicate entries without sorting them, enter:
view source
print?
1 gawk '!x[$0]++' filename

Key board shortcuts for linux

In this article I will show you some keyboard shortcuts and other command line tricks to make entering commands easier and faster. Learning them can make your life a lot easier!

Here are some keyboard shortcuts you can use within terminal:

Alt-r Undo all changes to the line.
Alt-Ctrl-e Expand command line.
Alt-p Non-incremental reverse search of history.
Alt-] x Moves the cursor forward to the next occurrence of x.
Alt-Ctrl-] x Moves the cursor backwards to the previous occurrence of x.
Ctrl-a Move to the start of the line.
Ctrl-e Move to the end of the line.
Ctrl-u Delete from the cursor to the beginning of the line.
Ctrl-k Delete from the cursor to the end of the line.
Ctrl-w Delete from the cursor to the start of the word.
Ctrl-y Pastes text from the clipboard.
Ctrl-l Clear the screen leaving the current line at the top of the screen.
Ctrl-x Ctrl-u Undo the last changes. Ctrl-_
Ctrl-r Incremental reverse search of history.
!! Execute last command in history
!abc Execute last command in history beginning with abc
!n Execute nth command in history
^abc^xyz Replace first occurrence of abc with xyz in last command and execute it

Recovery of the root pass word in BSD

The password cannot be recovered. The following procedure will allow you to change the root password.

Do the following:

- when the following boot message appears

Hit [ENTER] to boot immediately, or any other key for command prompt.
Booting [kernel] in 10 seconds...

hit a key, just pick one EXCEPT the ENTER key. You'll get a prompt like:

disk1s1a:>

- type the following commands:

disk1s1a:>unload all
disk1s1a:>load kernel
disk1s1a:>boot -s

The boot process will now start, just wait until it asks you for a shell. Just hit
ENTER and 'sh' will be used as shell.

If you type 'mount' you will see that only your root partition ( / ) is mounted, you will have to mount 'usr' partition as well.

#mount /dev/ad0s1f /usr

Now you have to mount root partition as read-write enabled. Use the following command:

#mount -u /

The root partition should now be mounted read-write. Now you can use 'passwd' program to
change the root password.

#passwd

That's all, reboot the system and login with the new password.

vi editor short cuts

vi is a family of screen-oriented text editors which share certain characteristics, such as methods of invocation from the operating system command interpreter, and characteristic user interface features. The portable subset of the behavior of vi programs, and the ex editor language supported within these programs, is described by the Single Unix Specification and POSIX.

vi operates in either insert mode (where typed text becomes part of the document) or normal mode (where keystrokes are interpreted as commands). Typing "i" while in normal mode switches the editor to insert mode. Typing "i" again at this point places an "i" in the document. From insert mode, pressing the escape key switches the editor back to normal mode.

vi basic commands

:set ic
ignore case differences when searching.
:set ai
set automatic indent.
:set sm
show matching ( or { with ) or } in insert mode.
:set nu
show line numbers.

down-arrow up-arrow
move down/up 1 line.
right-arrow left-arrow
move right/left 1 character column.
0 $
go to 1st/last column of current line.
return
go down to 1st printable character of next line.
nw nb
move right/left n words (1 word if n omitted).
ng
go to line n (end of file if n omitted).
ctrl-f ctrl-b
page forward/backward 1 screen.
ctrl-d ctrl-u
page forward/backward half a screen.
[[ ]]
go to beginning of current/next c function.

/expressionreturn
search forwards for expression.
?expressionreturn
search backwards for expression.
n n
repeat last / or ? command in same/reverse direction.

ytarget
copy (yank) text up to target to buffer.
y
copy current line to buffer.

itextesc
insert text before cursor.
otextesc
open new line below cursor and insert text.
r
replace character under cursor with next typed.
rtextesc
replace text.

backspace
in insert mode, delete character before cursor.
x x
delete character under/before cursor.
nx
delete n characters under and to right of cursor.
nx
delete n characters before cursor.
dd
delete current line.
ndd
delete n lines.
d
delete from cursor to end of line.

p p
put back yanked or deleted text below/above current line.
j
join current and next lines.
:m,n s/old/new/gc
global replace (g=every occurrence on line, c=prompt);

m=.
means from current position, n=$ means to eof.
u
undo last change.

:q
quit, provided no changes were made.
:q!
quit without saving.
:w
save (write) changes.
:m,n w file
save lines m through n (default=all) to file.
: x
save changes and quit.

How To change Ethernet network card speed and duplex settings in Linux

This tutorial will explain how to change network card speed and duplex settings in linux. It's working with any linux distributions like Fedora, CentOS, Debian, Ubuntu, etc.

ethtool is an Linux/Unix command allowing to modify the NIC parameters. ethtool can be used to query and change settings such as speed, negotiation and checksum offload on many network devices, especially Ethernet devices.

1. Install ethtool

Install ethtool in Fedora and CentOS:

# yum install ethtool

Install ethtool in Debian:

# apt-get install ethtool

Install ethtool in Ubuntu:

# sudo apt-get install ethtool

2. Using ethtool

You can check the current Ethernet network card speed and duplex settings using the following command

# ethtool eth0

or

# sudo ethtool eth0

if you are using Ubuntu.

eth0 is the Ethernet network card interface

Output:
Settings for eth0:
Supported ports: [ TP MII ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
Supports auto-negotiation: Yes
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
Advertised auto-negotiation: No
Speed: 100Mb/s
Duplex: Full
Port: MII
PHYAD: 1
Transceiver: internal
Auto-negotiation: off
Supports Wake-on: g
Wake-on: g
Current message level: 0x00000007 (7)
Link detected: yes

Turn off Auto-Negotiate feature using the following command

# ethtool -s eth0 autoneg off

or

# sudo ethtool -s eth0 autoneg off

if you are using Ubuntu.

3. ethtool Syntax

# ethtool -s eth0 speed SPEED duplex DUPLEX

Examples:

This example will show you how to setup your NIC speed 10 and half duplex
# ethtool -s eth0 speed 10 duplex half

This example will show you how to setup your NIC speed 100 and full duplex
# ethtool -s eth0 speed 100 duplex full

Monitoring Network traffic by process

NetHogs is a small network monitoring tool. Instead of breaking the traffic down per protocol or per subnet, like most tools do, it groups bandwidth by process. NetHogs does not rely on a special kernel module to be loaded. If there's suddenly a lot of network traffic, you can fire up NetHogs and immediately see which process is causing this. This makes it easy to indentify programs that have gone wild and are suddenly taking up your bandwidth.

To install NetHogs under CentOS, Fedora, RHEL, enter:
view source
print?
1 yum install nethogs

To install NetHogs under Debian and Ubuntu, enter:
view source
print?
1 apt-get install nethogs

The default network interface to monitor is eth0. If you wish to use other device, simply type the argument after nethog, open the terminal and run the following command:
view source
print?
1 nethogs eth0

usage: nethogs [-V] [-b] [-d seconds] [-t] [-p] [device [device [device ...]]]
-V : prints version.
-d : delay for update refresh rate in seconds. default is 1.
-t : tracemode.
-b : bughunt mode - implies tracemode.
-p : sniff in promiscious mode (not recommended).
device : device(s) to monitor. default is eth0

When nethogs is running, press:
q: quit
m: switch between total and kb/s modeNetHogs is a small network monitoring tool. Instead of breaking the traffic down per protocol or per subnet, like most tools do, it groups bandwidth by process. NetHogs does not rely on a special kernel module to be loaded. If there's suddenly a lot of network traffic, you can fire up NetHogs and immediately see which process is causing this. This makes it easy to indentify programs that have gone wild and are suddenly taking up your bandwidth.

To install NetHogs under CentOS, Fedora, RHEL, enter:
view source
print?
1 yum install nethogs

To install NetHogs under Debian and Ubuntu, enter:
view source
print?
1 apt-get install nethogs

The default network interface to monitor is eth0. If you wish to use other device, simply type the argument after nethog, open the terminal and run the following command:
view source
print?
1 nethogs eth0

usage: nethogs [-V] [-b] [-d seconds] [-t] [-p] [device [device [device ...]]]
-V : prints version.
-d : delay for update refresh rate in seconds. default is 1.
-t : tracemode.
-b : bughunt mode - implies tracemode.
-p : sniff in promiscious mode (not recommended).
device : device(s) to monitor. default is eth0

When nethogs is running, press:
q: quit
m: switch between total and kb/s mode

How to change MAC Address in Linux & BSD

Media Access Control address (MAC address) is a unique identifier assigned to most network adapters or network interface cards (NICs) by the manufacturer for identification, and used in the Media Access Control protocol sub-layer. If assigned by the manufacturer, a MAC address usually encodes the manufacturer's registered identification number. It may also be known as an Ethernet Hardware Address (EHA), hardware address, adapter address, or physical address.

1. Change MAC Address in Linux ( CentOS, Debian, Fedora, RHEL, Slackware, SuSE, Ubuntu )

# ifconfig [interface name] down
# ifconfig [interface name] hw ether [new MAC address]
# ifconfig [interface name] up

Example:

# ifconfig eth0 down
# ifconfig eth0 hw ether 1A:2B:3C:4D:5E:6F
# ifconfig eth0 up

2. Change MAC Address in FreeBSD

# ifconfig [interface name] down
# ifconfig [interface name] ether [new MAC address]
# ifconfig [interface name] up

Example:

# ifconfig xl0 down
# ifconfig xl0 ether 1A:2B:3C:4D:5E:6F
# ifconfig xl0 up

3. Change MAC address in HP-UX

Under HP-UX, you can change the MAC address in SAM by selecting Networking and Communications, then selecting the interface, then Action, Modify, Advanced Options. HP-UX refers to the MAC address as the "station address".

4. Change MAC address in IBM AIX

Set the physical MAC address for NIC.
# chdev -l ent0 -a
alt_addr= -P

Use the new MAC address.
use_alt_addr=yes -P

# reboot

5. Change MAC address in Mac OS X

Since Mac OS X 10.4.x (Darwin 8.x) onwards, the MAC address of wired Ethernet interface can be altered in Apple Mac OS X in a fashion similar to the FreeBSD/OpenBSD method.

# sudo ifconfig [interface name] down
# sudo ifconfig [interface name] ether 1A:2B:3C:4D:5E:6F
# sudo ifconfig [interface name] up

or

# sudo ifconfig [interface name] lladdr aa:bb:cc:dd:ee:ff (for Mac OS X 10.5 Leopard)

Example:

# sudo ifconfig en0 down
# sudo ifconfig en0 ether 1A:2B:3C:4D:5E:6F
# sudo ifconfig en0 up

or

# sudo ifconfig en0 down
# sudo ifconfig en0 lladdr 1A:2B:3C:4D:5E:6F
# sudo ifconfig en0 up

6. Change MAC address in OpenBSD

# ifconfig [interface name] down
# ifconfig [interface name] lladdr [new MAC address]
# ifconfig [interface name] up

Example:

# ifconfig bge1 down
# ifconfig bge1 lladdr 1A:2B:3C:4D:5E:6F
# ifconfig bge1 up

7. Change MAC address in Solaris

# ifconfig [interface name] down
# ifconfig [interface name] ether [new MAC address]
# ifconfig [interface name] up

Example:

# ifconfig hme0 down
# ifconfig hme0 ether 1A:2B:3C:4D:5E:6F
# ifconfig hme0 up

Monday, June 6, 2011

Converting fork() and exec() Usage to spawn()Converting fork() and exec() Usage to spawn()

The spawn() function provides a fast, low-overhead mechanism for creating a new POSIX process to run a new program. This is the typical usage of the POSIX.1 fork() function. OpenExtensions includes the POSIX.1d spawn() definition, which was included in the standard to handle the following operations in one function:

1. Create a new process.
2. Perform operations typically done in the new process to prepare to run a new program. This includes file descriptor mapping, changing process group membership, job control, and altering the signal handling environment.
3. Invoke the new program through exec().

To convert an application from using fork() and exec() to using spawn(), the following steps should be followed:

1. Replace the call to fork() with a call to spawn(), using the program name and program parameters from the exec() call.
2. Delete the call to exec().
3. Determine the other parameters to spawn() by examining the calls made between the fork() and the subsequent exec() to change the environment for the new program:
* Calls to dup2() should be replaced by entries in the file descriptor array.
* The mask value in any sigmask() calls should be used in the signal mask member of the inheritance structure.
* Signals whose actions are defaulted through sigaction() calls should be included in the sigdefault member of the inheritance structure.
* A call to setpgid() should be replaced by an entry in the process group member of the inheritance structure.
* A call to tcsetpgrp should be replaced by an entry in the inheritance structure.

Saturday, June 4, 2011

mmap()

Let’s consider a simple example program that uses mmap() to print a file chosen by the user to standard out:

#include
#include
#include
#include
#include
#include

int main (int argc, char *argv[])
{
struct stat sb;
off_t len;
char *p;
int fd;

if (argc < 2) { fprintf (stderr, "usage: %s \n", argv[0]);
return 1;
}

fd = open (argv[1], O_RDONLY);
if (fd == -1) {
perror ("open");
return 1;
}

if (fstat (fd, &sb) == -1) {
perror ("fstat");
return 1;
}

if (!S_ISREG (sb.st_mode)) {
fprintf (stderr, "%s is not a file\n", argv[1]);
return 1;
}

p = mmap (0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
if (p == MAP_FAILED) {
perror ("mmap");
return 1;
}

if (close (fd) == -1) {
perror ("close");
return 1;
}

for (len = 0; len < sb.st_size; len++)
putchar (p[len]);

if (munmap (p, sb.st_size) == -1) {
perror ("munmap");
return 1;
}

return 0;
}

The only unfamiliar system call in this example should befstat(), which we will cover in Chapter 7. All you need to know at this point is that fstat()returns information about a given file. TheS_ISREG()macro can check some of this information, so that we can ensure that the given file is a regular file (as opposed to a device file or a directory) before we map it. The behavior of nonregular files when mapped depends on the backing device. Some device files are mmap-able; other nonregular files are not mmap-able, and will seterrnotoEACCESS.

The rest of the example should be straightforward. The program is passed a filename as an argument. It opens the file, ensures it is a regular file, maps it, closes it, prints the file byte-by-byte to standard out, and then unmaps the file from memory.

Advantages of mmap()

Manipulating files via mmap() has a handful of advantages over the standard read() andwrite()system calls. Among them are:

1.
Reading from and writing to a memory-mapped file avoids the extraneous copy that occurs when using theread()orwrite()system calls, where the data must be copied to and from a user-space buffer.
2.
Aside from any potential page faults, reading from and writing to a memory-mapped file does not incur any system call or context switch overhead. It is as simple as accessing memory.
3.
When multiple processes map the same object into memory, the data is shared among all the processes. Read-only and shared writable mappings are shared in their entirety; private writable mappings have their not-yet-COW (copy-on-write) pages shared.
4.
Seeking around the mapping involves trivial pointer manipulations. There is no need for thelseek()system call.

For these reasons,mmap()is a smart choice for many applications.

Disadvantages of mmap()

There are a few points to keep in mind when using mmap():

1. Memory mappings are always an integer number of pages in size. Thus, the difference between the size of the backing file and an integer number of pages is “wasted” as slack space. For small files, a significant percentage of the mapping may be wasted. For example, with 4 KB pages, a 7 byte mapping wastes 4,089 bytes.
2. The memory mappings must fit into the process’ address space. With a 32-bit address space, a very large number of various-sized mappings can result in fragmentation of the address space, making it hard to find large free contiguous regions. This problem, of course, is much less apparent with a 64-bit address space.
3. There is overhead in creating and maintaining the memory mappings and associated data structures inside the kernel. This overhead is generally obviated by the elimination of the double copy mentioned in the previous section, particularly for larger and frequently accessed files.

For these reasons, the benefits ofmmap()are most greatly realized when the mapped file is large (and thus any wasted space is a small percentage of the total mapping), or when the total size of the mapped file is evenly divisible by the page size (and thus there is no wasted space).