So where can find the whole docbook ?  I could not find under
linux/Documentation directory.

Regards,
-hiren
(408)970-3062
[EMAIL PROTECTED]

> -----Original Message-----
> From: Erik Mouw [mailto:[EMAIL PROTECTED]]
> Sent: Wednesday, May 30, 2001 1:36 PM
> To: Tim Waugh
> Cc: Linux kernel mailing list; Alan Cox
> Subject: Re: [PATCH] Procfs Guide
> 
> 
> On Wed, May 30, 2001 at 09:30:48AM +0100, Tim Waugh wrote:
> > On Wed, May 30, 2001 at 01:29:17AM +0200, Erik Mouw wrote:
> > > I'm still looking for a proper way to automatically 
> include the example
> > > source into the SGML file, this patch with the same content in two
> > > files is a bit of an ugly hack.
> > 
> > Probably your best bet is to get the Makefile to pass a copy of the
> > real example source through sed to &entity;ify the bits that would
> > confuse SGML (<, >, etc), and into example.c.sed, make that into an
> > entity, and include it.
> > 
> > See <URL:http://people.redhat.com/twaugh/docbook/selfdocbook/> for
> > instance, which does this with its own SGML source.
> 
> Thanks, that was a really helpful example.
> 
> So how about this version?
> 
> 
> Erik
> 
> -- 
> J.A.K. (Erik) Mouw, Information and Communication Theory 
> Group, Department
> of Electrical Engineering, Faculty of Information Technology 
> and Systems,
> Delft University of Technology, PO BOX 5031,  2600 GA Delft, 
> The Netherlands
> Phone: +31-15-2783635  Fax: +31-15-2781843  Email: 
> [EMAIL PROTECTED]
> WWW: http://www-ict.its.tudelft.nl/~erik/
> 
> 
> Index: Documentation/DocBook/Makefile
> ===================================================================
> RCS file: /home/erik/cvsroot/elinux/Documentation/DocBook/Makefile,v
> retrieving revision 1.1.1.30
> retrieving revision 1.1.1.25.2.2
> diff -u -r1.1.1.30 -r1.1.1.25.2.2
> --- Documentation/DocBook/Makefile    2001/05/15 12:14:07     1.1.1.30
> +++ Documentation/DocBook/Makefile    2001/05/30 20:31:18     
> 1.1.1.25.2.2
> @@ -1,7 +1,7 @@
>  BOOKS        := wanbook.sgml z8530book.sgml mcabook.sgml 
> videobook.sgml \
>          kernel-api.sgml parportbook.sgml kernel-hacking.sgml \
>          kernel-locking.sgml via-audio.sgml mousedrivers.sgml 
> sis900.sgml \
> -        deviceiobook.sgml
> +        deviceiobook.sgml procfs-guide.sgml
>  
>  PS   :=      $(patsubst %.sgml, %.ps, $(BOOKS))
>  PDF  :=      $(patsubst %.sgml, %.pdf, $(BOOKS))
> @@ -9,6 +9,7 @@
>  IMG-parportbook := parport-share.fig parport-multi.fig 
> parport-structure.fig
>  EPS-parportbook := $(patsubst %.fig, %.eps, $(IMG-parportbook))
>  JPG-parportbook := $(patsubst %.fig, %.jpeg, $(IMG-parportbook))
> +C-procfs-example = procfs_example.sgml
>  
>  books:       $(BOOKS)
>  
> @@ -67,6 +68,17 @@
>       $(TOPDIR)/scripts/docgen 
> $(TOPDIR)/drivers/media/video/videodev.c \
>               <videobook.tmpl >videobook.sgml
>  
> +procfs_example.sgml: procfs_example.c
> +     echo "<programlisting>" > $@
> +     expand --tabs=8 < $< | \
> +     sed -e "s/&/\\&amp;/g" \
> +         -e "s/</\\&lt;/g" \
> +         -e "s/>/\\&gt;/g" >> $@
> +     echo "</programlisting>" >> $@
> +
> +procfs-guide.sgml:  procfs-guide.tmpl procfs_example.sgml
> +     $(TOPDIR)/scripts/docgen < procfs-guide.tmpl >$@
> +
>  APISOURCES :=        $(TOPDIR)/drivers/media/video/videodev.c \
>               $(TOPDIR)/arch/i386/kernel/irq.c \
>               $(TOPDIR)/arch/i386/kernel/mca.c \
> @@ -128,6 +140,7 @@
>       -$(RM) $(BOOKS)
>       -$(RM) $(DVI) $(AUX) $(TEX) $(LOG) $(OUT)
>       -$(RM) $(JPG-parportbook) $(EPS-parportbook)
> +     -$(RM) $(C-procfs-example)
>  
>  mrproper: clean
>       -$(RM) $(PS) $(PDF)
> Index: Documentation/DocBook/procfs-guide.tmpl
> ===================================================================
> RCS file: procfs-guide.tmpl
> diff -N procfs-guide.tmpl
> --- /dev/null Thu Mar 22 14:04:47 2001
> +++ Documentation/DocBook/procfs-guide.tmpl   Wed May 30 22:32:02 2001
> @@ -0,0 +1,603 @@
> +<!-- -*- sgml -*- -->
> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[
> +<!ENTITY procfsexample SYSTEM "procfs_example.sgml">
> +]>
> +
> +<book id="LKProcfsGuide">
> +  <bookinfo>
> +    <title>Linux Kernel Procfs Guide</title>
> +
> +
> +    <authorgroup>
> +      <author>
> +     <firstname>Erik</firstname>
> +     <othername>(J.A.K.)</othername>
> +     <surname>Mouw</surname>
> +     <affiliation>
> +       <orgname>Delft University of Technology</orgname>
> +       <orgdiv>Faculty of Information Technology and Systems</orgdiv>
> +       <address>
> +            <email>[EMAIL PROTECTED]</email>
> +            <pob>PO BOX 5031</pob>
> +            <postcode>2600 GA</postcode>
> +            <city>Delft</city>
> +            <country>The Netherlands</country>
> +          </address>
> +     </affiliation>
> +      </author>
> +    </authorgroup>
> +
> +
> +    <copyright>
> +      <year>2001</year>
> +      <holder>Erik Mouw</holder>
> +    </copyright>
> +
> +
> +    <legalnotice>
> +      <para>
> +        This documentation is free software; you can redistribute it
> +        and/or modify it under the terms of the GNU General Public
> +        License as published by the Free Software Foundation; either
> +        version 2 of the License, or (at your option) any later
> +        version.
> +      </para>
> +      
> +      <para>
> +        This documentation is distributed in the hope that it will be
> +        useful, but WITHOUT ANY WARRANTY; without even the implied
> +        warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
> +        PURPOSE.  See the GNU General Public License for 
> more details.
> +      </para>
> +      
> +      <para>
> +        You should have received a copy of the GNU General Public
> +        License along with this program; if not, write to the Free
> +        Software Foundation, Inc., 59 Temple Place, Suite 
> 330, Boston,
> +        MA 02111-1307 USA
> +      </para>
> +      
> +      <para>
> +        For more details see the file COPYING in the source
> +        distribution of Linux.
> +      </para>
> +    </legalnotice>
> +  </bookinfo>
> +
> +
> +
> +
> +  <toc>
> +  </toc>
> +
> +
> +
> +
> +  <preface>
> +    <title>Preface</title>
> +
> +    <para>
> +      This guide describes the use of the procfs file system from
> +      within the Linux kernel. The idea to write this guide 
> came up on
> +      the #kernelnewbies IRC channel (see <ulink
> +      
> url="http://www.kernelnewbies.org/";>http://www.kernelnewbies.o
> rg/</ulink>),
> +      when Jeff Garzik explained the use of procfs and forwarded me a
> +      message Alexander Viro wrote to the linux-kernel 
> mailing list. I
> +      agreed to write it up nicely, so here it is.
> +    </para>
> +
> +    <para>
> +      I'd like to thank Jeff Garzik
> +      <email>[EMAIL PROTECTED]</email> and Alexander Viro
> +      <email>[EMAIL PROTECTED]</email> for their input, and Tim Waugh
> +      <email>[EMAIL PROTECTED]</email> for his <ulink
> +      
> url="http://people.redhat.com/twaugh/docbook/selfdocbook/";>Sel
> fdocbook</ulink>.
> +    </para>
> +
> +    <para>
> +      This documentation was written while working on the LART
> +      computing board (<ulink
> +      
> url="http://www.lart.tudelft.nl/";>http://www.lart.tudelft.nl/<
> /ulink>).
> +      The development has been sponsored by the Mobile Multi-media
> +      Communications (<ulink
> +      
> url="http://www.mmc.tudelft.nl/";>http://www.mmc.tudelft.nl/</ulink>)
> +      and Ubiquitous Communications (<ulink
> +      
> url="http://www.ubicom.tudelft.nl/";>http://www.ubicom.tudelft.
> nl/</ulink>)
> +      projects.
> +    </para>
> +
> +    <para>
> +      Erik
> +    </para>
> +  </preface>
> +
> +
> +
> +
> +  <chapter id="intro">
> +    <title>Introduction</title>
> +
> +    <para>
> +      The <filename class="directory">/proc</filename> file system
> +      (procfs) is a special file system in the linux kernel. It's a
> +      virtual file system: it is not associated with a block 
> device but
> +      exists only in memory. The files in the procfs are 
> used to allow
> +      userland programs access to certain information from the kernel
> +      (like process information in <filename
> +      class="directory">/proc/[0-9]+/</filename>), but also for debug
> +      purposes (like <filename>/proc/ksyms</filename>).
> +    </para>
> +
> +    <para>
> +      This guide describes the use of the procfs file system from
> +      within the Linux kernel. It starts by introducing all relevant
> +      functions to manage the files within the file system. 
> After that
> +      it shows how to communicate with userland, and some tips and
> +      tricks will be pointed out. Finally a complete example will be
> +      shown.
> +    </para>
> +  </chapter>
> +
> +
> +
> +
> +  <chapter id="managing">
> +    <title>Managing procfs entries</title>
> +    
> +    <para>
> +      This chapter describes the functions that various kernel
> +      components use to populate the procfs with files, symlinks,
> +      device nodes, and directories.
> +    </para>
> +
> +    <para>
> +      A minor note before we start: if you want to use any of the
> +      procfs functions, be sure to include the correct header file! 
> +      This should be one of the first lines in your code:
> +    </para>
> +
> +    <programlisting>
> +#include &lt;linux/proc_fs.h&gt;
> +    </programlisting>
> +
> +
> +
> +
> +    <sect1 id="regularfile">
> +      <title>Creating a regular file</title>
> +      
> +      <funcsynopsis>
> +     <funcprototype>
> +       <funcdef>struct proc_dir_entry* 
> <function>create_proc_entry</function></funcdef>
> +       <paramdef>const char* <parameter>name</parameter></paramdef>
> +       <paramdef>mode_t <parameter>mode</parameter></paramdef>
> +       <paramdef>struct proc_dir_entry* 
> <parameter>parent</parameter></paramdef>
> +     </funcprototype>
> +      </funcsynopsis>
> +
> +      <para>
> +        This function creates a regular file with the name
> +        <parameter>name</parameter>, file mode
> +        <parameter>mode</parameter> in the directory
> +        <parameter>parent</parameter>. To create a file in 
> the root of
> +        the procfs, use <constant>NULL</constant> as
> +        <parameter>parent</parameter> parameter. When successful, the
> +        function will return a pointer to the freshly created
> +        <structname>struct proc_dir_entry</structname>; otherwise it
> +        will return <constant>NULL</constant>. <xref
> +        linkend="userland"> describes how to do something useful with
> +        regular files.
> +      <para>
> +
> +      <para>
> +        Note that it is specifically supported that you can pass a
> +        multi-directory path. For example
> +        
> <function>create_proc_entry</function>(<parameter>"drivers/via
0/info"</parameter>)
> +        will create the <filename class="directory">via0</filename>
> +        directory if necessary, with standard
> +        <constant>0755</constant> permissions.
> +      </para>
> +
> +    <para>
> +      If you only want to be able to read the file, the function
> +      <function>create_proc_read_entry</function> described in <xref
> +      linkend="convenience"> might be used to create and initialise
> +      the procfs entry in one single call.
> +    </para>
> +    </sect1>
> +
> +
> +
> +
> +    <sect1>
> +      <title>Creating a symlink</title>
> +
> +      <funcsynopsis>
> +     <funcprototype>
> +       <funcdef>struct proc_dir_entry*
> +       <function>proc_symlink</function></funcdef> <paramdef>const
> +       char* <parameter>name</parameter></paramdef>
> +       <paramdef>struct proc_dir_entry*
> +       <parameter>parent</parameter></paramdef> <paramdef>const
> +       char* <parameter>dest</parameter></paramdef>
> +     </funcprototype>
> +      </funcsynopsis>
> +      
> +      <para>
> +        This creates a symlink in the procfs directory
> +        <parameter>parent</parameter> that points from
> +        <parameter>name</parameter> to
> +        <parameter>dest</parameter>. This translates in userland to
> +        <literal>ln -s</literal> <parameter>dest</parameter>
> +        <parameter>name</parameter>.
> +      </para>
> +    </sect1>
> +
> +
> +
> +
> +    <sect1>
> +      <title>Creating a device</title>
> +
> +      <funcsynopsis>
> +     <funcprototype>
> +       <funcdef>struct proc_dir_entry* 
> <function>proc_mknod</function></funcdef>
> +       <paramdef>const char* <parameter>name</parameter></paramdef>
> +       <paramdef>mode_t <parameter>mode</parameter></paramdef>
> +       <paramdef>struct proc_dir_entry* 
> <parameter>parent</parameter></paramdef>
> +       <paramdef>kdev_t <parameter>rdev</parameter></paramdef>
> +     </funcprototype>
> +      </funcsynopsis>
> +      
> +      <para>
> +        Creates a device file <parameter>name</parameter> with mode
> +        <parameter>mode</parameter> in the procfs directory
> +        <parameter>parent</parameter>. The device file will work on
> +        the device <parameter>rdev</parameter>, which can be 
> generated
> +        by using the <literal>MKDEV</literal> macro from
> +        <literal>linux/kdev_t.h</literal>. The
> +        <parameter>mode</parameter> parameter
> +        <emphasis>must</emphasis> contain 
> <constant>S_IFBLK</constant>
> +        or <constant>S_IFCHR</constant> to create a device
> +        node. Compare with userland <literal>mknod
> +        --mode=</literal><parameter>mode</parameter>
> +        <parameter>name</parameter> <parameter>rdev</parameter>.
> +      </para>
> +    </sect1>
> +
> +
> +
> +
> +    <sect1>
> +      <title>Creating a directory</title>
> +      
> +      <funcsynopsis>
> +     <funcprototype>
> +       <funcdef>struct proc_dir_entry* 
> <function>proc_mkdir</function></funcdef>
> +       <paramdef>const char* <parameter>name</parameter></paramdef>
> +       <paramdef>struct proc_dir_entry* 
> <parameter>parent</parameter></paramdef>
> +     </funcprototype>
> +      </funcsynopsis>
> +
> +      <para>
> +        Create a directory <parameter>name</parameter> in the procfs
> +        directory <parameter>parent</parameter>.
> +      </para>
> +    </sect1>
> +
> +
> +
> +
> +    <sect1>
> +      <title>Removing an entry</title>
> +      
> +      <funcsynopsis>
> +     <funcprototype>
> +       <funcdef>void <function>remove_proc_entry</function></funcdef>
> +       <paramdef>const char* <parameter>name</parameter></paramdef>
> +       <paramdef>struct proc_dir_entry* 
> <parameter>parent</parameter></paramdef>
> +     </funcprototype>
> +      </funcsynopsis>
> +
> +      <para>
> +        Removes the entry <parameter>name</parameter> in the 
> directory
> +        <parameter>parent</parameter> from the procfs. Note that
> +        entries are removed by their 
> <emphasis>name</emphasis>, not by
> +        the <structname>struct proc_dir_entry</structname> 
> returned by the
> +        various create functions.
> +      </para>
> +      
> +      <para>
> +        Note that the <structfield>data</structfield> entry from the
> +        <structname>struct proc_dir_entry</structname>> has 
> to be freed
> +        before this function is called (that is: if there was some
> +        <structfield>data</structfield> allocated, of course). See
> +        <xref linkend="usingdata"> for more information on using the
> +        <structfield>data</structfield> entry.
> +      </para>
> +    </sect1>
> +  </chapter>
> +
> +
> +
> +
> +  <chapter id="userland">
> +    <title>Communicating with userland</title>
> +    
> +    <para>
> +       Instead of reading (or writing) the information directly from
> +       kernel memory, the procfs works with <emphasis>call back
> +       functions</emphasis> for files: functions that are called when
> +       a specific file is being read or written. Those functions have
> +       to be initialised after the procfs file is created by setting
> +       the <structfield>read_proc</structfield> and/or
> +       <structfield>write_proc</structfield> fields in the
> +       <structname>struct proc_dir_entry*</structname> the function
> +       <function>create_proc_entry</function> returned:
> +    </para>
> +
> +    <programlisting>
> +struct proc_dir_entry* entry;
> +
> +entry->read_proc = read_proc_foo;
> +entry->write_proc = write_proc_foo;
> +    </programlisting>
> +
> +    <para>
> +      If you only want to use a the
> +      <structfield>read_proc</structfield>, the function
> +      <function>create_proc_read_entry</function> described in <xref
> +      linkend="convenience"> might be used to create and initialise
> +      the procfs entry in one single call.
> +    </para>
> +
> +
> +
> +    <sect1>
> +      <title>Reading data</title>
> +
> +      <para>
> +        The read function is a call back function that 
> allows userland
> +        processes to read data from the kernel. The read function
> +        should have the following format:
> +      </para>
> +
> +      <funcsynopsis>
> +     <funcprototype>
> +       <funcdef>int <function>read_func</function></funcdef>
> +       <paramdef>char* <parameter>page</parameter></paramdef>
> +       <paramdef>char** <parameter>start</parameter></paramdef>
> +       <paramdef>off_t <parameter>off</parameter></paramdef>
> +       <paramdef>int <parameter>count</parameter></paramdef>
> +       <paramdef>int* <parameter>eof</parameter></paramdef>
> +       <paramdef>void* <parameter>data</parameter></paramdef>
> +     </funcprototype>
> +      </funcsynopsis>
> +
> +      <para>
> +        The read function should write its information into the
> +        <parameter>page</parameter>. For proper use, the function
> +        should start writing at an offset of
> +        <parameter>off</parameter> in <parameter>page</parameter> and
> +        write <parameter>count</parameter> bytes at maximum, but
> +        because most read functions are quite simple and 
> only return a
> +        small amount of information, these two parameters are usually
> +        ignored (it breaks pagers like <literal>more</literal> and
> +        <literal>less</literal>, but <literal>cat</literal> still
> +        works).
> +      </para>
> +
> +      <para>
> +        If the <parameter>off</parameter> and
> +        <parameter>count</parameter> parameters are properly used,
> +        <parameter>eof</parameter> should be used to signal that the
> +        end of the file has been reached by writing
> +        <literal>1</literal> to the memory location
> +        <parameter>eof</parameter> points to.
> +      </para>
> +
> +      <para>
> +        The parameter <parameter>start</parameter> doesn't seem to be
> +        used anywhere in the kernel. The <parameter>data</parameter>
> +        parameter can be used to use a single call back function for
> +        several files, see <xref linkend="usingdata">.
> +      </para>
> +
> +      <para>
> +        The <function>read_func</function> function must return the
> +        number of bytes written into the <parameter>page</parameter>.
> +      </para>
> +
> +      <para>
> +        <xref linkend="example"> shows how to use a read call back
> +        function.
> +      </para>
> +    </sect1>
> +
> +
> +
> +
> +    <sect1>
> +      <title>Writing data</title>
> +
> +      <para>
> +        The write call back function allows a userland 
> process to write
> +        data to the kernel, so it has some kind of control over the
> +        kernel. The write function should have the following format:
> +      </para>
> +
> +      <funcsynopsis>
> +     <funcprototype>
> +       <funcdef>int <function>write_func</function></funcdef>
> +       <paramdef>struct file* <parameter>file</parameter></paramdef>
> +       <paramdef>const char* <parameter>buffer</parameter></paramdef>
> +       <paramdef>unsigned long 
> <parameter>count</parameter></paramdef>
> +       <paramdef>void* <parameter>data</parameter></paramdef>
> +     </funcprototype>
> +      </funcsynopsis>
> +
> +      <para>
> +        The write function should read <parameter>count</parameter>
> +        bytes at maximum from the <parameter>buffer</parameter>. Note
> +        that the <parameter>buffer</parameter> doesn't live in the
> +        kernel's memory space, so it should first be copied to kernel
> +        space with <function>copy_from_user</function>. The
> +        <parameter>file</parameter> parameter is usually
> +        ignored. <xref linkend="usingdata"> shows how to use the
> +        <parameter>data</parameter> parameter.
> +      </para>
> +
> +      <para>
> +        Again, <xref linkend="example"> shows how to use 
> this call back
> +        function.
> +      </para>
> +    </sect1>
> +
> +
> +
> +
> +    <sect1 id="usingdata">
> +      <title>A single call back for many files</title>
> +
> +      <para>
> +         When a large number of almost identical files is used, it's
> +         quite inconvenient to use a separate call back function for
> +         each file. Instead of that, a single call back 
> function can be
> +         used that distinguishes between the files by using
> +         <structfield>data</structfield> field in <structname>struct
> +         proc_dir_entry</structname>. First of all, the
> +         <structfield>data</structfield> field has to be initialised:
> +      </para>
> +
> +      <programlisting>
> +struct proc_dir_entry* entry;
> +struct my_file_data *file_data;
> +
> +file_data = kmalloc(sizeof(struct my_file_data), GFP_KERNEL);
> +entry->data = file_data;
> +      </programlisting>
> +     
> +      <para>
> +          The <structfield>data</structfield> field is a <type>void
> +          *</type>, so it can be initialised with anything.
> +      </para>
> +
> +      <para>
> +        Now that the <structfield>data</structfield> field 
> is set, the
> +        <function>read_proc</function> and
> +        <function>write_proc</function> can use it to distinguish
> +        between files because they get it passed into their
> +        <parameter>data</parameter> parameter:
> +      </para>
> +
> +      <programlisting>
> +int foo_read_func(char *page, char **start, off_t off,
> +                  int count, int *eof, void *data)
> +{
> +        int len;
> +
> +        if(data == file_data) {
> +                /* special case for this file */
> +        } else {
> +                /* normal processing */
> +        }
> +
> +        return len;
> +}
> +      </programlisting>
> +
> +      <para>
> +        Be sure to free the <structfield>data</structfield> 
> data field
> +        when removing the procfs entry.
> +      </para>
> +    </sect1>
> +  </chapter>
> +
> +
> +
> +
> +  <chapter id="tips">
> +    <title>Tips and tricks</title>
> +
> +
> +
> +
> +    <sect1 id="convenience">
> +      <title>Convenience functions</title>
> +
> +      <funcsynopsis>
> +     <funcprototype>
> +       <funcdef>struct proc_dir_entry* 
> <function>create_proc_read_entry</function></funcdef>
> +       <paramdef>const char* <parameter>name</parameter></paramdef>
> +       <paramdef>mode_t <parameter>mode</parameter></paramdef>
> +       <paramdef>struct proc_dir_entry* 
> <parameter>parent</parameter></paramdef>
> +       <paramdef>read_proc_t* 
> <parameter>read_proc</parameter></paramdef>
> +       <paramdef>void* <parameter>data</parameter></paramdef>
> +     </funcprototype>
> +      </funcsynopsis>
> +      
> +      <para>
> +        This function creates a regular file in exactly the same way
> +        as <function>create_proc_entry</function> from <xref
> +        linkend="regularfile"> does, but also allows to set the read
> +        function <parameter>read_proc</parameter> in one call. This
> +        function is also able to set the <parameter>data</parameter>,
> +        as explained in <xref linkend="usingdata">.
> +      </para>
> +    </sect1>
> +
> +
> +
> +    <sect1>
> +      <title>Modules</title>
> +
> +      <para>
> +        If the procfs is being used from within a module, be sure to
> +        set the <structfield>owner</structfield> field in the
> +        <structname>struct proc_dir_entry</structname> to
> +        <constant>THIS_MODULE</constant>.
> +      <para>
> +
> +      <programlisting>
> +struct proc_dir_entry* entry;
> +
> +entry->owner = THIS_MODULE;
> +      </programlisting>
> +    </sect1>
> +
> +
> +
> +
> +    <sect1>
> +      <title>Mode and ownership</title>
> +
> +      <para>
> +        Sometimes it is useful to change the mode and/or 
> ownership of a
> +        procfs entry. Here is an example how to achieve that:
> +      </para>
> +
> +      <programlisting>
> +struct proc_dir_entry* entry;
> +
> +entry->mode =  S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH;
> +entry->uid = 0;
> +entry->gid = 100;
> +      </programlisting>
> +
> +    </sect1>
> +  </chapter>
> +
> +
> +
> +
> +  <chapter id="example">
> +    <title>Example</title>
> +
> +    <!-- be careful with the example code: it shouldn't be wider than
> +    approx. 60 columns, or otherwise it won't fit properly on a page
> +    -->
> +
> +&procfsexample;
> +
> +  </chapter>
> +</book>
> Index: Documentation/DocBook/procfs_example.c
> ===================================================================
> RCS file: procfs_example.c
> diff -N procfs_example.c
> --- /dev/null Thu Mar 22 14:04:47 2001
> +++ Documentation/DocBook/procfs_example.c    Wed May 30 22:32:02 2001
> @@ -0,0 +1,247 @@
> +/*
> + * procfs_example.c: an example proc interface
> + *
> + * Copyright (C) 2001, Erik Mouw ([EMAIL PROTECTED])
> + *
> + * This file accompanies the procfs-guide in the Linux kernel
> + * source. It's main use is to demonstrate the concepts and
> + * functions described in the guide.
> + *
> + * This software has been developed while working on the LART
> + * computing board (http://www.lart.tudelft.nl/). The
> + * development has been sponsored by the Mobile Multi-media
> + * Communications (http://www.mmc.tudelft.nl/) and Ubiquitous
> + * Communications (http://www.ubicom.tudelft.nl/) projects.
> + *
> + * The author can be reached at:
> + *
> + *  Erik Mouw
> + *  Information and Communication Theory Group
> + *  Faculty of Information Technology and Systems
> + *  Delft University of Technology
> + *  P.O. Box 5031
> + *  2600 GA Delft
> + *  The Netherlands
> + *
> + *
> + * This program is free software; you can redistribute
> + * it and/or modify it under the terms of the GNU General
> + * Public License as published by the Free Software
> + * Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + *
> + * This program is distributed in the hope that it will be
> + * useful, but WITHOUT ANY WARRANTY; without even the implied
> + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
> + * PURPOSE.  See the GNU General Public License for more
> + * details.
> + * 
> + * You should have received a copy of the GNU General Public
> + * License along with this program; if not, write to the
> + * Free Software Foundation, Inc., 59 Temple Place,
> + * Suite 330, Boston, MA  02111-1307  USA
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/proc_fs.h>
> +#include <linux/sched.h>
> +#include <asm/uaccess.h>
> +
> +
> +#define MODULE_VERSION "1.0"
> +#define MODULE_NAME "procfs_example"
> +
> +#define FOOBAR_LEN 8
> +
> +struct fb_data_t {
> +     char name[FOOBAR_LEN + 1];
> +     char value[FOOBAR_LEN + 1];
> +};
> +
> +
> +static struct proc_dir_entry *example_dir, *foo_file,
> +     *bar_file, *jiffies_file, *tty_device, *symlink;
> +
> +
> +struct fb_data_t foo_data, bar_data;
> +
> +
> +static int proc_read_jiffies(char *page, char **start,
> +                          off_t off, int count,
> +                          int *eof, void *data)
> +{
> +     int len;
> +
> +     MOD_INC_USE_COUNT;
> +     
> +     len = sprintf(page, "jiffies = %ld\n",
> +                      jiffies);
> +
> +     MOD_DEC_USE_COUNT;
> +
> +     return len;
> +}
> +
> +
> +static int proc_read_foobar(char *page, char **start,
> +                         off_t off, int count, 
> +                         int *eof, void *data)
> +{
> +     int len;
> +     struct fb_data_t *fb_data = (struct fb_data_t *)data;
> +
> +     MOD_INC_USE_COUNT;
> +     
> +     len = sprintf(page, "%s = '%s'\n", 
> +                   fb_data->name, fb_data->value);
> +
> +     MOD_DEC_USE_COUNT;
> +
> +     return len;
> +}
> +
> +
> +static int proc_write_foobar(struct file *file,
> +                          const char *buffer,
> +                          unsigned long count, 
> +                          void *data)
> +{
> +     int len;
> +     struct fb_data_t *fb_data = (struct fb_data_t *)data;
> +
> +     MOD_INC_USE_COUNT;
> +
> +     if(count > FOOBAR_LEN)
> +             len = FOOBAR_LEN;
> +     else
> +             len = count;
> +
> +     if(copy_from_user(fb_data->value, buffer, len)) {
> +             MOD_DEC_USE_COUNT;
> +             return -EFAULT;
> +     }
> +
> +     fb_data->value[len] = '\0';
> +
> +     MOD_DEC_USE_COUNT;
> +
> +     return len;
> +}
> +
> +
> +static int __init init_procfs_example(void)
> +{
> +     int rv = 0;
> +
> +     /* create directory */
> +     example_dir = proc_mkdir(MODULE_NAME, NULL);
> +     if(example_dir == NULL) {
> +             rv = -ENOMEM;
> +             goto out;
> +     }
> +     
> +     example_dir->owner = THIS_MODULE;
> +     
> +     /* create jiffies using convenience function */
> +     jiffies_file = create_proc_read_entry("jiffies", 
> +                                           0444, example_dir, 
> +                                           proc_read_jiffies,
> +                                           NULL);
> +     if(jiffies_file == NULL) {
> +             rv  = -ENOMEM;
> +             goto no_jiffies;
> +     }
> +
> +     jiffies_file->owner = THIS_MODULE;
> +
> +     /* create foo and bar files using same callback functions */
> +     foo_file = create_proc_entry("foo", 0644, example_dir);
> +     if(foo_file == NULL) {
> +             rv = -ENOMEM;
> +             goto no_foo;
> +     }
> +
> +     strcpy(foo_data.name, "foo");
> +     strcpy(foo_data.value, "foo");
> +     foo_file->data = &foo_data;
> +     foo_file->read_proc = proc_read_foobar;
> +     foo_file->write_proc = proc_write_foobar;
> +     foo_file->owner = THIS_MODULE;
> +             
> +     bar_file = create_proc_entry("bar", 0644, example_dir);
> +     if(bar_file == NULL) {
> +             rv = -ENOMEM;
> +             goto no_bar;
> +     }
> +
> +     strcpy(bar_data.name, "bar");
> +     strcpy(bar_data.value, "bar");
> +     bar_file->data = &bar_data;
> +     bar_file->read_proc = proc_read_foobar;
> +     bar_file->write_proc = proc_write_foobar;
> +     bar_file->owner = THIS_MODULE;
> +             
> +     /* create tty device */
> +     tty_device = proc_mknod("tty", S_IFCHR | 0666,
> +                             example_dir, MKDEV(5, 0));
> +     if(tty_device == NULL) {
> +             rv = -ENOMEM;
> +             goto no_tty;
> +     }
> +     
> +     tty_device->owner = THIS_MODULE;
> +
> +     /* create symlink */
> +     symlink = proc_symlink("jiffies_too", example_dir, 
> +                            "jiffies");
> +     if(symlink == NULL) {
> +             rv = -ENOMEM;
> +             goto no_symlink;
> +     }
> +
> +     symlink->owner = THIS_MODULE;
> +
> +     /* everything OK */
> +     printk(KERN_INFO "%s %s initialised\n",
> +            MODULE_NAME, MODULE_VERSION);
> +     return 0;
> +
> +no_symlink:
> +     remove_proc_entry("tty", example_dir);
> +no_tty:
> +     remove_proc_entry("bar", example_dir);
> +no_bar:
> +     remove_proc_entry("foo", example_dir);
> +no_foo:
> +     remove_proc_entry("jiffies", example_dir);
> +no_jiffies:                        
> +     remove_proc_entry(MODULE_NAME, NULL);
> +out:
> +     return rv;
> +}
> +
> +
> +static void __exit cleanup_procfs_example(void)
> +{
> +     remove_proc_entry("jiffies_too", example_dir);
> +     remove_proc_entry("tty", example_dir);
> +     remove_proc_entry("bar", example_dir);
> +     remove_proc_entry("foo", example_dir);
> +     remove_proc_entry("jiffies", example_dir);
> +     remove_proc_entry(MODULE_NAME, NULL);
> +
> +     printk(KERN_INFO "%s %s removed\n",
> +            MODULE_NAME, MODULE_VERSION);
> +}
> +
> +
> +module_init(init_procfs_example);
> +module_exit(cleanup_procfs_example);
> +
> +MODULE_AUTHOR("Erik Mouw");
> +MODULE_DESCRIPTION("procfs examples");
> +
> +EXPORT_NO_SYMBOLS;
> 
> 
> -
> To unsubscribe from this list: send the line "unsubscribe 
> linux-kernel" in
> the body of a message to [EMAIL PROTECTED]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to