This chapter introduced the following symbols and header files.
#include <linux/ioctl.h>
This header declares all the macros used to define
ioctl commands. It is currently included by
<linux/fs.h>
.
_IOC_NRBITS
,
_IOC_TYPEBITS
,
_IOC_SIZEBITS
,
_IOC_DIRBITS
The number of bits available for the different bitfields of
ioctl commands. There are also four macros that
specify the MASK
s and four that specify the
SHIFT
s, but they’re mainly for internal
use. _IOC_SIZEBITS
is an important value to check,
because it changes across architectures.
_IOC_NONE
,
_IOC_READ
,
_IOC_WRITE
The possible values for the “direction” bitfield. “Read” and “write” are different bits and can be OR’d to specify read/write. The values are 0 based.
_IOC(dir,type,nr,size)
,
_IO(type,nr)
,
_IOR(type,nr,size)
,
_IOW(type,nr,size)
,
_IOWR(type,nr,size)
_IOC_DIR(nr)
,
_IOC_TYPE(nr)
,
_IOC_NR(nr)
,
_IOC_SIZE(nr)
Macros used to decode a command. In particular,
_IOC_TYPE(nr)
is an OR combination of
_IOC_READ
and _IOC_WRITE
.
#include <asm/uaccess.h>
,
int access_ok(int type, const void *addr, unsigned long size);
This function checks that a pointer to user space is actually usable. access_ok returns a nonzero value if the access should be allowed.
VERIFY_READ
,
VERIFY_WRITE
The possible values for the type
argument in
access_ok. VERIFY_WRITE
is a
superset of VERIFY_READ
.
#include <asm/uaccess.h>
,
int put_user(datum,ptr);
,
int get_user(local,ptr);
,
int __put_user(datum,ptr);
,
int __get_user(local,ptr);
Macros used to store or retrieve a datum to or from user space. The
number of bytes being transferred depends on
sizeof(*ptr)
. The regular versions call
access_ok first, while the qualified versions
(__put_user and
__get_user) assume that
access_ok has already been called.
#include <linux/capability.h>
Defines the various CAP_
symbols for capabilities
under Linux 2.2 and later.
int capable(int capability);
#include <linux/wait.h>
,
typedef struct { /* ... */ } wait_queue_head_t;
,
void init_waitqueue_head(wait_queue_head_t *queue);
,
DECLARE_WAIT_QUEUE_HEAD(queue);
The defined type for Linux wait queues. A
wait_queue_head_t
must be explicitly initialized
with either init_waitqueue_head at runtime or
declare_wait_queue_head at compile time.
#include <linux/sched.h>
,
void interruptible_sleep_on(wait_queue_head_t *q);
,
void sleep_on(wait_queue_head_t *q);
,
void interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout);
,
void sleep_on_timeout(wait_queue_head_t *q, long timeout);
Calling any of these functions puts the current process to sleep on a queue. Usually, you’ll choose the interruptible form to implement blocking read and write.
void wake_up(struct wait_queue **q);
,
void wake_up_interruptible(struct wait_queue **q);
,
void wake_up_sync(struct wait_queue **q);
,
void wake_up_interruptible_sync(struct wait_queue **q);
These functions wake processes that are sleeping on the queue
q
. The _interruptible form
wakes only interruptible processes. The _sync
versions will not reschedule the CPU before returning.
typedef struct { /* ... */ } wait_queue_t;
,
init_waitqueue_entry(wait_queue_t *entry, struct task_struct *task);
The wait_queue_t
type is used when sleeping without
calling sleep_on. Wait queue entries must be
initialized prior to use; the task
argument used is
almost always current
.
void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
,
void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait);
,
void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait);
These functions add an entry to a wait queue; add_wait_queue_exclusive adds the entry to the end of the queue for exclusive waits. Entries should be removed from the queue after sleeping with remove_wait_queue.
void wait_event(wait_queue_head_t q, int condition);
,
int wait_event_interruptible(wait_queue_head_t q, int condition);
These two macros will cause the process to sleep on the given queue
until the given condition
evaluates to a true
value.
void schedule(void);
This function selects a runnable process from the run queue. The
chosen process can be current
or a different
one. You won’t usually call schedule directly,
because the sleep_on functions do it internally.
#include <linux/poll.h>
,
void poll_wait(struct file *filp, wait_queue_head_t *q, poll_table *p)
This function puts the current process into a wait queue without scheduling immediately. It is designed to be used by the poll method of device drivers.
int fasync_helper(struct inode *inode, struct file *filp, int mode, struct fasync_struct **fa);
This function is a “helper” for implementing the
fasync device method. The mode
argument is the same value that is passed to the method, while
fa
points to a device-specific
fasync_struct *
.
void kill_fasync(struct fasync_struct *fa, int sig, int band);
If the driver supports asynchronous notification, this function can be
used to send a signal to processes registered in
fa
.
#include <linux/spinlock.h>
,
typedef struct { /* ... */ } spinlock_t;
,
void spin_lock_init(spinlock_t *lock);
The spinlock_t
type defines a spinlock, which must
be initialized (with spin_lock_init) prior to
use.
spin_lock(spinlock_t *lock);
,
spin_unlock(spinlock_t *lock);
spin_lock locks the given lock, perhaps waiting until it becomes available. The lock can then be released with spin_unlock.