📄 procfs-guide.tmpl
字号:
<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. Entries are removed by their <emphasis>name</emphasis>, not by the <structname>struct proc_dir_entry</structname> returned by the various create functions. Note that this function doesn't recursively remove entries. </para> <para> Be sure to free the <structfield>data</structfield> entry from the <structname>struct proc_dir_entry</structname> before <function>remove_proc_entry</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) information directly from kernel memory, procfs works with <emphasis>call back functions</emphasis> for files: functions that are called when a specific file is being read or written. Such 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> that 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"> may 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 at most <parameter>count</parameter> bytes, 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 create 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. A better approach is to have a single call back function that distinguishes between the files by using the <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 can set the <parameter>data</parameter> as well, like explained in <xref linkend="usingdata">. </para> </sect1> <sect1> <title>Modules</title> <para> If 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 that shows 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>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -