📄 node22.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<!--Converted with LaTeX2HTML 98.1 release (February 19th, 1998)
originally by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds
* revised and updated by: Marcus Hennecke, Ross Moore, Herb Swan
* with significant contributions from:
Jens Lippmann, Marek Rouchal, Martin Wilck and others -->
<HTML>
<HEAD>
<TITLE>Replacing printk's</TITLE>
<META NAME="description" CONTENT="Replacing printk's">
<META NAME="keywords" CONTENT="mpg">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<LINK REL="STYLESHEET" HREF="mpg.css">
<LINK REL="next" HREF="node23.html">
<LINK REL="previous" HREF="node21.html">
<LINK REL="up" HREF="mpg.html">
<LINK REL="next" HREF="node23.html">
</HEAD>
<BODY >
<!--Navigation Panel-->
<A NAME="tex2html647"
HREF="node23.html">
<IMG WIDTH="37" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="next"
SRC="next_motif.gif"></A>
<A NAME="tex2html643"
HREF="mpg.html">
<IMG WIDTH="26" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="up"
SRC="up_motif.gif"></A>
<A NAME="tex2html637"
HREF="node21.html">
<IMG WIDTH="63" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="previous"
SRC="previous_motif.gif"></A>
<A NAME="tex2html645"
HREF="node1.html">
<IMG WIDTH="65" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="contents"
SRC="contents_motif.gif"></A>
<A NAME="tex2html646"
HREF="node34.html">
<IMG WIDTH="43" HEIGHT="24" ALIGN="BOTTOM" BORDER="0" ALT="index"
SRC="index_motif.gif"></A>
<BR>
<B> Next:</B> <A NAME="tex2html648"
HREF="node23.html">Scheduling Tasks</A>
<B> Up:</B> <A NAME="tex2html644"
HREF="mpg.html">Linux Kernel Module Programming</A>
<B> Previous:</B> <A NAME="tex2html638"
HREF="node21.html">Blocking Processes</A>
<BR>
<BR>
<!--End of Navigation Panel-->
<H1><A NAME="SECTION001100000000000000000"> </A><A NAME="printk"> </A><A NAME="605"> </A>
<A NAME="606"> </A>
<BR>
Replacing printk's
</H1>
<P>
In the beginning (chapter <A HREF="node11.html#hello-world">1</A>), I said that X and kernel
module programming don't mix. That's true while developing the kernel
module, but in actual use you want to be able to send messages to
whichever tty<A NAME="tex2html217"
HREF="footnode.html#foot855"><SUP>9.1</SUP></A> the command to the module came from. This is important for
identifying errors after the kernel module is released, because it will be
used through all of them.
<P>
The way this is done is by using <TT>current</TT>, a pointer to the currently
running task,
to get the current task's tty structure. Then, we look inside that tty
structure to find a pointer to a string write function, which we use to
write a string to the tty.
<A NAME="611"> </A><A NAME="612"> </A>
<A NAME="613"> </A><A NAME="614"> </A>
<P>
ex
<FONT SIZE="+1"><B>printk.c</B></FONT>
<A NAME="619"> </A><A NAME="620"> </A>
<P>
<PRE>
/* printk.c - send textual output to the tty you're
* running on, regardless of whether it's passed
* through X11, telnet, etc. */
/* Copyright (C) 1998 by Ori Pomerantz */
/* The necessary header files */
/* Standard in kernel modules */
#include <linux/kernel.h> /* We're doing kernel work */
#include <linux/module.h> /* Specifically, a module */
/* Deal with CONFIG_MODVERSIONS */
#if CONFIG_MODVERSIONS==1
#define MODVERSIONS
#include <linux/modversions.h>
#endif
/* Necessary here */
#include <linux/sched.h> /* For current */
#include <linux/tty.h> /* For the tty declarations */
/* Print the string to the appropriate tty, the one
* the current task uses */
void print_string(char *str)
{
struct tty_struct *my_tty;
/* The tty for the current task */
my_tty = current->tty;
/* If my_tty is NULL, it means that the current task
* has no tty you can print to (this is possible, for
* example, if it's a daemon). In this case, there's
* nothing we can do. */
if (my_tty != NULL) {
/* my_tty->driver is a struct which holds the tty's
* functions, one of which (write) is used to
* write strings to the tty. It can be used to take
* a string either from the user's memory segment
* or the kernel's memory segment.
*
* The function's first parameter is the tty to
* write to, because the same function would
* normally be used for all tty's of a certain type.
* The second parameter controls whether the
* function receives a string from kernel memory
* (false, 0) or from user memory (true, non zero).
* The third parameter is a pointer to a string,
* and the fourth parameter is the length of
* the string.
*/
(*(my_tty->driver).write)(
my_tty, /* The tty itself */
0, /* We don't take the string from user space */
str, /* String */
strlen(str)); /* Length */
/* ttys were originally hardware devices, which
* (usually) adhered strictly to the ASCII standard.
* According to ASCII, to move to a new line you
* need two characters, a carriage return and a
* line feed. In Unix, on the other hand, the
* ASCII line feed is used for both purposes - so
* we can't just use \n, because it wouldn't have
* a carriage return and the next line will
* start at the column right
* after the line feed.
*
* BTW, this is the reason why the text file
* is different between Unix and Windows.
* In CP/M and its derivatives, such as MS-DOS and
* Windows, the ASCII standard was strictly
* adhered to, and therefore a new line requires
* both a line feed and a carriage return.
*/
(*(my_tty->driver).write)(
my_tty,
0,
"\015\012",
2);
}
}
/* Module initialization and cleanup ****************** */
/* Initialize the module - register the proc file */
int init_module()
{
print_string("Module Inserted");
return 0;
}
/* Cleanup - unregister our file from /proc */
void cleanup_module()
{
print_string("Module Removed");
}
</PRE>
<P>
<BR><HR>
<ADDRESS>
<I></I>
<BR><I>1999-05-19</I>
</ADDRESS>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -