Next Previous Contents

4. Common Routines

printk() <include/linux/kernel.h>

printk feeds kernel messages to the console, dmesg, and the syslog daemon. It is useful for debugging and reporting errors, and can be used inside interrupt contect, but use with caution: a machine which has its console flooded with printk messages is unusable. It uses a format string mostly compatible with ANSI C printf, and C string concatenation to give it a first "priority" argument:

            printk(KERN_INFO "i = %u\n", i);

See include/linux/kernel.h for other KERN_ values; these are interpreted by syslog as the level. Special case: for printing an IP address use

            __u32 ipaddress;
            printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));

printk internally uses a 1K buffer and does not catch overruns. Make sure that will be enough.

Sidenote: you will know when you are a real kernel hacker when you start typoing printf as printk in your user programs :)

Another sidenote: the original Unix Version 6 sources had a comment on top of its printf function: "Printf should not be used for chit-chat". You should follow that advice.

copy_to_user()/copy_from_user()/get_user()/put_user() <include/asm/uaccess.h> <SLEEPS>

put_user() and get_user() are used to get and put single values (such as an int, char, or long) from and to userspace. A pointer into userspace should never be simply dereferenced: data should be copied using these routines. Both return -EFAULT or 0.

copy_to_user() and copy_from_user() are more general: they copy an aritrary amount of data to and from userspace. Unlike put_user() and get_user(), they return the amount of uncopied data (ie. 0 still means success).

The functions may sleep implicitely. This should never be called outside user context (it makes no sense), with interrupts disabled, or a spinlock held.

kmalloc()/kfree() <include/linux/slab.h> <MAY SLEEP: SEE BELOW>

These routines are used to dynamically request pointer-aligned chunks of memory, like malloc and free do in userspace, but kmalloc() takes an extra flag word. Important values:

  1. GFP_KERNEL: May sleep and swap to free memory. Only allowed in user context, but is the most reliable way to allocate memory.
  2. GFP_ATOMIC: Don't sleep. Less reliable than GFP_KERNEL, but may be called from interrupt context. You should really have a good out-of-memory error handling strategy.
  3. GFP_DMA: Allocate ISA DMA lower than 16MB. If you don't know what that is you don't need it. Very unreliable.

If you see a ``kmem_grow: Called nonatomically from int'' warning message you called a memory allocation function from interrupt context without GFP_ATOMIC. You should really fix that.

If you are allocating at least PAGE_SIZE <include/asm/page.h> bytes, consider using __get_free_pages() <include/linux/mm.h>. It takes an order argument (0 for page sized, 1 for double page, 2 for four pages etc.) and the same memory priority flag word as above.

If you are allocating more than a page worth of bytes you can use vmalloc(). It'll allocate virtual memory in the kernel map. This block is not contiguous in physical memory, but the MMU makes it look like it is for you (so it'll only look contiguous to the CPUs, not to external device drivers). If you really need large physically contiguous memory for some weird device, you have a problem: it is poorly supported in Linux because after some time memory fragmentation in a running kernel makes it hard. The best way is to allocate the block early in the boot process.

Before inventing your own cache of often-used objects consider using a slab cache <include/linux/slab.h>.

current <include/asm/current.h>

This global variable (really a macro) contains a pointer to the current task structure, so is only valid in user context. For example, when a process makes a system call, this will point to the task structure of the calling process.

__init, __exit & __initdata <include/linux/init.h>

After boot, the kernel frees up a special section; functions marked with `__init' and data structures marked with `__initdata' are dropped after boot is complete (within modules this directive is currently ignored). `__exit' is used to declare a function which is only required on exit: the function will be dropped if this file is not compiled as a module. See the header file for use.


Next Previous Contents