⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 supporting functions.htm

📁 What is this ``device driver stuff anyway? Here s a very short introduction to the concept.
💻 HTM
📖 第 1 页 / 共 3 页
字号:
</p><h4><tt>IS_*(inode)</tt></h4>
<tt>IS_RDONLY(inode) ((inode)-&gt;i_flags &amp; MS_RDONLY)</tt><br>
<tt>IS_NOSUID(inode) ((inode)-&gt;i_flags &amp; MS_NOSUID)</tt><br>
<tt>IS_NODEV(inode) ((inode)-&gt;i_flags &amp; MS_NODEV)</tt><br>
<tt>IS_NOEXEC(inode) ((inode)-&gt;i_flags &amp; MS_NOEXEC)</tt><br>
<tt>IS_SYNC(inode) ((inode)-&gt;i_flags &amp; MS_SYNC)</tt><br>
<tt>#include &lt;linux/fs.h&gt;</tt>

<p>These five test to see if the inode is on a filesystem
mounted the corresponding flag.




</p><h4><tt>kfree*()</tt></h4>
<tt>#define kfree(x) kfree_s((x), 0)</tt><br>
<tt>void kfree_s(void * obj, int size)</tt><br>
<tt>#include &lt;linux/malloc.h&gt;</tt>

<p>Free memory previously allocated with <tt>kmalloc()</tt>.
There are two possible arguments:
</p><dl>
<dt><tt>obj</tt>
</dt><dd>Pointer to kernel memory to free.
</dd><dt><tt>size</tt>
</dt><dd>To speed this up, if you know the size, use
<tt>kfree_s()</tt> and provide the correct size.  This way, the kernel memory
allocator knows which bucket cache the object belongs to, and doesn't
have to search all of the buckets.  (For more details on this
terminology, read mm/kmalloc.c.)
</dd></dl>

<p><b>[<tt>kfree_s()</tt> may be obsolete now.]</b>

</p><p><b>Defined in:</b> mm/kmalloc.c, include/linux/malloc.h<br>
<b>See also:</b> <tt>kmalloc()</tt>.





</p><h4><tt>kmalloc()</tt></h4>
<tt>void * kmalloc(unsigned int len, int priority)</tt><br>
<tt>#include &lt;linux/kernel.h&gt;</tt>

<p><tt>kmalloc()</tt> used to be limited to 4096 bytes.  It is
now limited to 131056 bytes ((32*4096)-16) on Linux/Intel, and
twice that on platforms such as Alpha with 8Kb pages.  Buckets,
which used to be all exact powers of 2, are now a power of 2
minus some small number, except for numbers less than or equal
to 128.  For more details, see the implementation in
mm/kmalloc.c.

</p><p><tt>kmalloc()</tt> takes two arguments:
</p><dl>
<dt><tt>len</tt>
</dt><dd>Length of memory to allocate.  If the maximum is
exceeded, kmalloc will log an error message of ``<tt>kmalloc of too large
a block (%d bytes).</tt>'' and return <tt>NULL</tt>.
</dd><dt><tt>priority</tt>
</dt><dd><tt>GFP_KERNEL</tt> or <tt>GFP_ATOMIC</tt>.  If
<tt>GFP_KERNEL</tt> is chosen, <tt>kmalloc()</tt> may sleep,
allowing pre-emption to occur.  This is the normal way of
calling <tt>kmalloc()</tt>.  However, there are cases where it
is better to return immediately if no pages are available,
without attempting to sleep to find one.  One of the places in
which this is true is in the swapping code, because it could
cause race conditions, and another in the networking code,
where things can happen at much faster speed that things could
be handled by swapping to disk to make space for giving the
networking code more memory.  The most important reason for
using <tt>GFP_ATOMIC</tt> is if it is being called from an
interrupt, when you cannot sleep, and cannot receive other
interrupts.

</dd><dt><b>Returns:</b>
</dt><dd><tt>NULL</tt> on failure.<br>
Pointer to allocated memory on success.
</dd></dl>

<b>Defined in:</b> mm/kmalloc.c<br>
<b>See also:</b> <tt>kfree()</tt>



<h4><tt>ll_rw_block()</tt></h4>
<tt>void ll_rw_block(int rw, int nr, struct buffer_head *bh[])</tt><br>
<tt>#include &lt;linux/fs.h&gt;</tt>

<p>No device driver will ever call this code: it is called only
through the buffer cache.  However, an understanding of this
function may help you understand the function of the strategy
routine.

</p><p>After sanity checking, if there are no pending requests on
the device's request queue, <tt>ll_rw_block()</tt> ``plugs''
the queue so that the requests don't go out until all the
requests are in the queue, sorted by the elevator algorithm.
<tt>make_request()</tt> is then called for each request.  If
the queue had to be plugged, then the strategy routine for that
device is not active, and it is called, <b>with interrupts
disabled.  It is the responsibility of the strategy routine to
re-enable interrupts.</b>

</p><p><b>Defined in:</b> devices/block/ll_rw_block.c<br>
<b>See also:</b> <tt>make_request()</tt>, <tt>add_request()</tt>.




</p><h4><tt>MAJOR()</tt></h4>
<tt>#define MAJOR(a) (((unsigned)(a))&gt;&gt;8)</tt><br>
<tt>#include &lt;linux/fs.h&gt;</tt>

<p>This takes a 16 bit device number and gives the associated
major number by shifting off the minor number.

</p><p><b>See also:</b> <tt>MINOR()</tt>.




</p><h4><tt>make_request()</tt></h4>
<tt>static void make_request(int major, int rw, struct buffer_head *bh)</tt><br>

<p>This is a static function in ll_rw_block.c, and cannot be
called by other code.  However, an understanding of this
function, as well as an understanding of
<tt>ll_rw_block()</tt>, may help you understand the strategy
routine.

</p><p><tt>make_request()</tt> first checks to see if the request
is readahead or writeahead and the buffer is locked.  If so, it
simply ignores the request and returns.  Otherwise, it locks
the buffer and, except for SCSI devices, checks to make sure
that write requests don't fill the queue, as read requests
should take precedence.

</p><p>If no spaces are available in the queue, and the request is
neither readahead nor writeahead, <tt>make_request()</tt>
sleeps on the event <tt>wait_for_request</tt>, and tries again
when woken.  When a space in the queue is found, the request
information is filled in and <tt>add_request()</tt> is called
to actually add the request to the queue.

<b>Defined in:</b> devices/block/ll_rw_block.c<br>
<b>See also:</b> <tt>add_request()</tt>, <tt>ll_rw_block()</tt>.




</p><h4><tt>MINOR()</tt></h4>
<tt>#define MINOR(a) ((a)&amp;0xff)</tt><br>
<tt>#include &lt;linux/fs.h&gt;</tt>

<p>This takes a 16 bit device number and gives the associated
minor number by masking off the major number.

</p><p><b>See also:</b> <tt>MAJOR()</tt>.




</p><h4><tt>memcpy_*fs()</tt></h4>
<tt>inline void memcpy_tofs(void * to, const void * from, unsigned long n)</tt><br>
<tt>inline void memcpy_fromfs(void * to, const void * from, unsigned long n)</tt><br>
<tt>#include &lt;asm/segment.h&gt;</tt>

<p>Copies memory between user space and kernel space in chunks
larger than one byte, word, or long.  Be very careful to get
the order of the arguments right!

</p><p><img src="supporting%20functions_files/warning.gif" alt="[Caution!] "><b>Note:</b>
these functions may cause implicit I/O, if the memory being
accessed has been swapped out, and therefore pre-emption may
occur at this point.  Do not include these functions in
critical sections of your code, even if the critical sections
are protected by <tt>cli()</tt>/<tt>sti()</tt> pairs, because
implicit I/O will violate the <tt>cli()</tt> protection.  If
you need to get at user-space memory, copy it to kernel-space
memory <i>before</i> you enter your critical section.

</p><p>These functions take three arguments:
</p><dl>
<dt><tt>to</tt>
</dt><dd>Address to copy data to.
</dd><dt><tt>from</tt>
</dt><dd>Address to copy data from.
</dd><dt><tt>n</tt>
</dt><dd>Number of bytes to copy.
</dd></dl>

<p><b>Defined in:</b> include/asm/segment.h<br>
<b>See also:</b> <tt>get_user()</tt>, <tt>put_user()</tt>, <tt>cli()</tt>,
<tt>sti()</tt>.




</p><h4><tt>outb(), outb_p()</tt></h4>
<tt>inline void outb(char value, unsigned short port)</tt><br>
<tt>inline void outb_p(char value, unsigned short port)</tt><br>
<tt>#include &lt;asm/io.h&gt;</tt>

<p>Writes a byte to a port.  <tt>outb()</tt> goes as fast as it
can, while <tt>outb_p()</tt> pauses before returning.  Some
devices are happier if you don't write to them as fast as
possible.  Both functions take two arguments:
</p><dl>
<dt><tt>value</tt>
</dt><dd>The byte to write.
</dd><dt><tt>port</tt>
</dt><dd>Port to write byte to.
</dd></dl>

<p><b>Defined in:</b> include/asm/io.h<br>
<b>See also:</b> <tt>inb()</tt>, <tt>inb_p()</tt>.



</p><h4><tt>printk()</tt></h4>
<tt>int printk(const char* fmt, ...)</tt><br>
<tt>#include &lt;linux/kernel.h&gt;</tt>

<p><tt>printk()</tt> is a version of <tt>printf()</tt> for the
kernel, with some restrictions.  It cannot handle floats, and
has a few other limitations, which are documented in
kernel/vsprintf.c.  It takes a variable number of arguments:
</p><dl>
<dt><tt>fmt</tt>
</dt><dd>Format string, <tt>printf()</tt> style.
</dd><dt><tt>...</tt>
</dt><dd>The rest of the arguments, <tt>printf()</tt> style.
</dd><dt><b>Returns:</b>
</dt><dd>Number of bytes written.
</dd></dl>

<p><img src="supporting%20functions_files/warning.gif" alt="[Caution!]"><b>Note:</b> 
<tt>printk()</tt> may cause implicit I/O, if the memory being
accessed has been swapped out, and therefore pre-emption may
occur at this point.  Also, <tt>printk()</tt> will set the
interrupt enable flag, so <b>never use it in code protected
by <tt>cli()</tt>.</b> Because it causes I/O, it is not safe to
use in protected code anyway, even it if didn't set the
interrupt enable flag.

</p><p><b>Defined in:</b> kernel/printk.c.



</p><h4><tt>put_user()</tt></h4>
<tt>#define put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr)))</tt><br>
<tt>#include &lt;asm/segment.h&gt;</tt>

<p>Allows a driver to write data in user space, which is in a
different segment than the kernel. Derives the type of the
arguments and the storage size automatically. <b>This means that
you have to use types correctly.  Shoddy typing will simply
fail to work.</b>

</p><p><img src="supporting%20functions_files/warning.gif" alt="[Caution!] "><b>Note:</b>
these functions may cause implicit I/O, if the memory being
accessed has been swapped out, and therefore pre-emption may
occur at this point.  Do not include these functions in
critical sections of your code even if the critical sections
are protected by <tt>cli()</tt>/<tt>sti()</tt> pairs, because
that implicit I/O will violate the integrity of your
<tt>cli()</tt>/<tt>sti()</tt> pair.  If you need to get at
user-space memory, copy it to kernel-space memory <i>before</i>
you enter your critical section.

</p><p>These functions take two arguments:
</p><dl>
<dt><tt>val</tt>
</dt><dd>Value to write
</dd><dt><tt>addr</tt>
</dt><dd>Address to write data to.
</dd></dl>

<p><b>Defined in:</b> asm/segment.h<br>
<b>See also:</b> <tt>memcpy_*fs()</tt>, <tt>get_user()</tt>, <tt>cli()</tt>,
<tt>sti()</tt>.




</p><h4><tt>register_*dev()</tt></h4>
<tt>int register_chrdev(unsigned int major, const char *name, struct file_operations *fops)</tt><br>
<tt>int register_blkdev(unsigned int major, const char *name, struct file_operations *fops)</tt><br>
<tt>#include &lt;linux/fs.h&gt;</tt><br>
<tt>#include &lt;linux/errno.h&gt;</tt>

<p>Registers a device with the kernel, letting the kernel check
to make sure that no other driver has already grabbed the same
major number. Takes three arguments:
</p><dl>
<dt><tt>major</tt>
</dt><dd>Major number of device being registered.
</dd><dt><tt>name</tt>
</dt><dd>Unique string identifying driver.  Used in the
output for the /proc/devices file.
</dd><dt><tt>fops</tt>
</dt><dd>Pointer to a <tt>file_operations</tt> structure for
that device.  This must <b>not</b> be <tt>NULL</tt>, or the kernel will
panic later.
</dd><dt><b>Returns:</b>
</dt><dd><tt>-EINVAL</tt> if major is &gt;= <tt>MAX_CHRDEV</tt> or
<tt>MAX_BLKDEV</tt> (defined in <tt><linux></linux></tt>), for character or
block devices, respectively.<br>
<tt>-EBUSY</tt> if major device number has already been allocated.<br>
0 on success.
</dd></dl>

<p><b>Defined in:</b> fs/devices.c<br>
<b>See also:</b> <tt>unregister_*dev()</tt>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -