Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | <?xml version="1.0" encoding="UTF-8"?> |
| 2 | <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" |
| 3 | "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ |
| 4 | <!ENTITY procfsexample SYSTEM "procfs_example.xml"> |
| 5 | ]> |
| 6 | |
| 7 | <book id="LKProcfsGuide"> |
| 8 | <bookinfo> |
| 9 | <title>Linux Kernel Procfs Guide</title> |
| 10 | |
| 11 | <authorgroup> |
| 12 | <author> |
| 13 | <firstname>Erik</firstname> |
| 14 | <othername>(J.A.K.)</othername> |
| 15 | <surname>Mouw</surname> |
| 16 | <affiliation> |
| 17 | <orgname>Delft University of Technology</orgname> |
| 18 | <orgdiv>Faculty of Information Technology and Systems</orgdiv> |
| 19 | <address> |
| 20 | <email>J.A.K.Mouw@its.tudelft.nl</email> |
| 21 | <pob>PO BOX 5031</pob> |
| 22 | <postcode>2600 GA</postcode> |
| 23 | <city>Delft</city> |
| 24 | <country>The Netherlands</country> |
| 25 | </address> |
| 26 | </affiliation> |
| 27 | </author> |
| 28 | </authorgroup> |
| 29 | |
| 30 | <revhistory> |
| 31 | <revision> |
| 32 | <revnumber>1.0 </revnumber> |
| 33 | <date>May 30, 2001</date> |
| 34 | <revremark>Initial revision posted to linux-kernel</revremark> |
| 35 | </revision> |
| 36 | <revision> |
| 37 | <revnumber>1.1 </revnumber> |
| 38 | <date>June 3, 2001</date> |
| 39 | <revremark>Revised after comments from linux-kernel</revremark> |
| 40 | </revision> |
| 41 | </revhistory> |
| 42 | |
| 43 | <copyright> |
| 44 | <year>2001</year> |
| 45 | <holder>Erik Mouw</holder> |
| 46 | </copyright> |
| 47 | |
| 48 | |
| 49 | <legalnotice> |
| 50 | <para> |
| 51 | This documentation is free software; you can redistribute it |
| 52 | and/or modify it under the terms of the GNU General Public |
| 53 | License as published by the Free Software Foundation; either |
| 54 | version 2 of the License, or (at your option) any later |
| 55 | version. |
| 56 | </para> |
| 57 | |
| 58 | <para> |
| 59 | This documentation is distributed in the hope that it will be |
| 60 | useful, but WITHOUT ANY WARRANTY; without even the implied |
| 61 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
| 62 | PURPOSE. See the GNU General Public License for more details. |
| 63 | </para> |
| 64 | |
| 65 | <para> |
| 66 | You should have received a copy of the GNU General Public |
| 67 | License along with this program; if not, write to the Free |
| 68 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
| 69 | MA 02111-1307 USA |
| 70 | </para> |
| 71 | |
| 72 | <para> |
| 73 | For more details see the file COPYING in the source |
| 74 | distribution of Linux. |
| 75 | </para> |
| 76 | </legalnotice> |
| 77 | </bookinfo> |
| 78 | |
| 79 | |
| 80 | |
| 81 | |
| 82 | <toc> |
| 83 | </toc> |
| 84 | |
| 85 | |
| 86 | |
| 87 | |
Rob Landley | 9de476b | 2008-02-07 00:13:31 -0800 | [diff] [blame] | 88 | <preface id="Preface"> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 89 | <title>Preface</title> |
| 90 | |
| 91 | <para> |
| 92 | This guide describes the use of the procfs file system from |
| 93 | within the Linux kernel. The idea to write this guide came up on |
| 94 | the #kernelnewbies IRC channel (see <ulink |
| 95 | url="http://www.kernelnewbies.org/">http://www.kernelnewbies.org/</ulink>), |
| 96 | when Jeff Garzik explained the use of procfs and forwarded me a |
| 97 | message Alexander Viro wrote to the linux-kernel mailing list. I |
| 98 | agreed to write it up nicely, so here it is. |
| 99 | </para> |
| 100 | |
| 101 | <para> |
| 102 | I'd like to thank Jeff Garzik |
| 103 | <email>jgarzik@pobox.com</email> and Alexander Viro |
| 104 | <email>viro@parcelfarce.linux.theplanet.co.uk</email> for their input, |
| 105 | Tim Waugh <email>twaugh@redhat.com</email> for his <ulink |
| 106 | url="http://people.redhat.com/twaugh/docbook/selfdocbook/">Selfdocbook</ulink>, |
| 107 | and Marc Joosen <email>marcj@historia.et.tudelft.nl</email> for |
| 108 | proofreading. |
| 109 | </para> |
| 110 | |
| 111 | <para> |
| 112 | This documentation was written while working on the LART |
| 113 | computing board (<ulink |
| 114 | url="http://www.lart.tudelft.nl/">http://www.lart.tudelft.nl/</ulink>), |
| 115 | which is sponsored by the Mobile Multi-media Communications |
| 116 | (<ulink |
| 117 | url="http://www.mmc.tudelft.nl/">http://www.mmc.tudelft.nl/</ulink>) |
| 118 | and Ubiquitous Communications (<ulink |
| 119 | url="http://www.ubicom.tudelft.nl/">http://www.ubicom.tudelft.nl/</ulink>) |
| 120 | projects. |
| 121 | </para> |
| 122 | |
| 123 | <para> |
| 124 | Erik |
| 125 | </para> |
| 126 | </preface> |
| 127 | |
| 128 | |
| 129 | |
| 130 | |
| 131 | <chapter id="intro"> |
| 132 | <title>Introduction</title> |
| 133 | |
| 134 | <para> |
| 135 | The <filename class="directory">/proc</filename> file system |
| 136 | (procfs) is a special file system in the linux kernel. It's a |
| 137 | virtual file system: it is not associated with a block device |
| 138 | but exists only in memory. The files in the procfs are there to |
| 139 | allow userland programs access to certain information from the |
| 140 | kernel (like process information in <filename |
| 141 | class="directory">/proc/[0-9]+/</filename>), but also for debug |
| 142 | purposes (like <filename>/proc/ksyms</filename>). |
| 143 | </para> |
| 144 | |
| 145 | <para> |
| 146 | This guide describes the use of the procfs file system from |
| 147 | within the Linux kernel. It starts by introducing all relevant |
| 148 | functions to manage the files within the file system. After that |
| 149 | it shows how to communicate with userland, and some tips and |
| 150 | tricks will be pointed out. Finally a complete example will be |
| 151 | shown. |
| 152 | </para> |
| 153 | |
| 154 | <para> |
| 155 | Note that the files in <filename |
| 156 | class="directory">/proc/sys</filename> are sysctl files: they |
| 157 | don't belong to procfs and are governed by a completely |
| 158 | different API described in the Kernel API book. |
| 159 | </para> |
| 160 | </chapter> |
| 161 | |
| 162 | |
| 163 | |
| 164 | |
| 165 | <chapter id="managing"> |
| 166 | <title>Managing procfs entries</title> |
| 167 | |
| 168 | <para> |
| 169 | This chapter describes the functions that various kernel |
| 170 | components use to populate the procfs with files, symlinks, |
| 171 | device nodes, and directories. |
| 172 | </para> |
| 173 | |
| 174 | <para> |
| 175 | A minor note before we start: if you want to use any of the |
| 176 | procfs functions, be sure to include the correct header file! |
| 177 | This should be one of the first lines in your code: |
| 178 | </para> |
| 179 | |
| 180 | <programlisting> |
| 181 | #include <linux/proc_fs.h> |
| 182 | </programlisting> |
| 183 | |
| 184 | |
| 185 | |
| 186 | |
| 187 | <sect1 id="regularfile"> |
| 188 | <title>Creating a regular file</title> |
| 189 | |
| 190 | <funcsynopsis> |
| 191 | <funcprototype> |
| 192 | <funcdef>struct proc_dir_entry* <function>create_proc_entry</function></funcdef> |
| 193 | <paramdef>const char* <parameter>name</parameter></paramdef> |
| 194 | <paramdef>mode_t <parameter>mode</parameter></paramdef> |
| 195 | <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef> |
| 196 | </funcprototype> |
| 197 | </funcsynopsis> |
| 198 | |
| 199 | <para> |
| 200 | This function creates a regular file with the name |
| 201 | <parameter>name</parameter>, file mode |
| 202 | <parameter>mode</parameter> in the directory |
| 203 | <parameter>parent</parameter>. To create a file in the root of |
| 204 | the procfs, use <constant>NULL</constant> as |
| 205 | <parameter>parent</parameter> parameter. When successful, the |
| 206 | function will return a pointer to the freshly created |
| 207 | <structname>struct proc_dir_entry</structname>; otherwise it |
| 208 | will return <constant>NULL</constant>. <xref |
| 209 | linkend="userland"/> describes how to do something useful with |
| 210 | regular files. |
| 211 | </para> |
| 212 | |
| 213 | <para> |
| 214 | Note that it is specifically supported that you can pass a |
| 215 | path that spans multiple directories. For example |
| 216 | <function>create_proc_entry</function>(<parameter>"drivers/via0/info"</parameter>) |
| 217 | will create the <filename class="directory">via0</filename> |
| 218 | directory if necessary, with standard |
| 219 | <constant>0755</constant> permissions. |
| 220 | </para> |
| 221 | |
| 222 | <para> |
| 223 | If you only want to be able to read the file, the function |
| 224 | <function>create_proc_read_entry</function> described in <xref |
| 225 | linkend="convenience"/> may be used to create and initialise |
| 226 | the procfs entry in one single call. |
| 227 | </para> |
| 228 | </sect1> |
| 229 | |
| 230 | |
| 231 | |
| 232 | |
Rob Landley | 9de476b | 2008-02-07 00:13:31 -0800 | [diff] [blame] | 233 | <sect1 id="Creating_a_symlink"> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 234 | <title>Creating a symlink</title> |
| 235 | |
| 236 | <funcsynopsis> |
| 237 | <funcprototype> |
| 238 | <funcdef>struct proc_dir_entry* |
| 239 | <function>proc_symlink</function></funcdef> <paramdef>const |
| 240 | char* <parameter>name</parameter></paramdef> |
| 241 | <paramdef>struct proc_dir_entry* |
| 242 | <parameter>parent</parameter></paramdef> <paramdef>const |
| 243 | char* <parameter>dest</parameter></paramdef> |
| 244 | </funcprototype> |
| 245 | </funcsynopsis> |
| 246 | |
| 247 | <para> |
| 248 | This creates a symlink in the procfs directory |
| 249 | <parameter>parent</parameter> that points from |
| 250 | <parameter>name</parameter> to |
| 251 | <parameter>dest</parameter>. This translates in userland to |
| 252 | <literal>ln -s</literal> <parameter>dest</parameter> |
| 253 | <parameter>name</parameter>. |
| 254 | </para> |
| 255 | </sect1> |
| 256 | |
Rob Landley | 9de476b | 2008-02-07 00:13:31 -0800 | [diff] [blame] | 257 | <sect1 id="Creating_a_directory"> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 258 | <title>Creating a directory</title> |
| 259 | |
| 260 | <funcsynopsis> |
| 261 | <funcprototype> |
| 262 | <funcdef>struct proc_dir_entry* <function>proc_mkdir</function></funcdef> |
| 263 | <paramdef>const char* <parameter>name</parameter></paramdef> |
| 264 | <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef> |
| 265 | </funcprototype> |
| 266 | </funcsynopsis> |
| 267 | |
| 268 | <para> |
| 269 | Create a directory <parameter>name</parameter> in the procfs |
| 270 | directory <parameter>parent</parameter>. |
| 271 | </para> |
| 272 | </sect1> |
| 273 | |
| 274 | |
| 275 | |
| 276 | |
Rob Landley | 9de476b | 2008-02-07 00:13:31 -0800 | [diff] [blame] | 277 | <sect1 id="Removing_an_entry"> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 278 | <title>Removing an entry</title> |
| 279 | |
| 280 | <funcsynopsis> |
| 281 | <funcprototype> |
| 282 | <funcdef>void <function>remove_proc_entry</function></funcdef> |
| 283 | <paramdef>const char* <parameter>name</parameter></paramdef> |
| 284 | <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef> |
| 285 | </funcprototype> |
| 286 | </funcsynopsis> |
| 287 | |
| 288 | <para> |
| 289 | Removes the entry <parameter>name</parameter> in the directory |
| 290 | <parameter>parent</parameter> from the procfs. Entries are |
| 291 | removed by their <emphasis>name</emphasis>, not by the |
| 292 | <structname>struct proc_dir_entry</structname> returned by the |
| 293 | various create functions. Note that this function doesn't |
| 294 | recursively remove entries. |
| 295 | </para> |
| 296 | |
| 297 | <para> |
| 298 | Be sure to free the <structfield>data</structfield> entry from |
| 299 | the <structname>struct proc_dir_entry</structname> before |
| 300 | <function>remove_proc_entry</function> is called (that is: if |
| 301 | there was some <structfield>data</structfield> allocated, of |
| 302 | course). See <xref linkend="usingdata"/> for more information |
| 303 | on using the <structfield>data</structfield> entry. |
| 304 | </para> |
| 305 | </sect1> |
| 306 | </chapter> |
| 307 | |
| 308 | |
| 309 | |
| 310 | |
| 311 | <chapter id="userland"> |
| 312 | <title>Communicating with userland</title> |
| 313 | |
| 314 | <para> |
| 315 | Instead of reading (or writing) information directly from |
| 316 | kernel memory, procfs works with <emphasis>call back |
| 317 | functions</emphasis> for files: functions that are called when |
| 318 | a specific file is being read or written. Such functions have |
| 319 | to be initialised after the procfs file is created by setting |
| 320 | the <structfield>read_proc</structfield> and/or |
| 321 | <structfield>write_proc</structfield> fields in the |
| 322 | <structname>struct proc_dir_entry*</structname> that the |
| 323 | function <function>create_proc_entry</function> returned: |
| 324 | </para> |
| 325 | |
| 326 | <programlisting> |
| 327 | struct proc_dir_entry* entry; |
| 328 | |
| 329 | entry->read_proc = read_proc_foo; |
| 330 | entry->write_proc = write_proc_foo; |
| 331 | </programlisting> |
| 332 | |
| 333 | <para> |
| 334 | If you only want to use a the |
| 335 | <structfield>read_proc</structfield>, the function |
| 336 | <function>create_proc_read_entry</function> described in <xref |
| 337 | linkend="convenience"/> may be used to create and initialise the |
| 338 | procfs entry in one single call. |
| 339 | </para> |
| 340 | |
| 341 | |
| 342 | |
Rob Landley | 9de476b | 2008-02-07 00:13:31 -0800 | [diff] [blame] | 343 | <sect1 id="Reading_data"> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 344 | <title>Reading data</title> |
| 345 | |
| 346 | <para> |
| 347 | The read function is a call back function that allows userland |
| 348 | processes to read data from the kernel. The read function |
| 349 | should have the following format: |
| 350 | </para> |
| 351 | |
| 352 | <funcsynopsis> |
| 353 | <funcprototype> |
| 354 | <funcdef>int <function>read_func</function></funcdef> |
C. Scott Ananian | 6b86e85 | 2007-07-15 23:41:13 -0700 | [diff] [blame] | 355 | <paramdef>char* <parameter>buffer</parameter></paramdef> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 356 | <paramdef>char** <parameter>start</parameter></paramdef> |
| 357 | <paramdef>off_t <parameter>off</parameter></paramdef> |
| 358 | <paramdef>int <parameter>count</parameter></paramdef> |
C. Scott Ananian | 6b86e85 | 2007-07-15 23:41:13 -0700 | [diff] [blame] | 359 | <paramdef>int* <parameter>peof</parameter></paramdef> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 360 | <paramdef>void* <parameter>data</parameter></paramdef> |
| 361 | </funcprototype> |
| 362 | </funcsynopsis> |
| 363 | |
| 364 | <para> |
| 365 | The read function should write its information into the |
C. Scott Ananian | 6b86e85 | 2007-07-15 23:41:13 -0700 | [diff] [blame] | 366 | <parameter>buffer</parameter>, which will be exactly |
| 367 | <literal>PAGE_SIZE</literal> bytes long. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 368 | </para> |
| 369 | |
| 370 | <para> |
C. Scott Ananian | 6b86e85 | 2007-07-15 23:41:13 -0700 | [diff] [blame] | 371 | The parameter |
| 372 | <parameter>peof</parameter> should be used to signal that the |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 373 | end of the file has been reached by writing |
| 374 | <literal>1</literal> to the memory location |
C. Scott Ananian | 6b86e85 | 2007-07-15 23:41:13 -0700 | [diff] [blame] | 375 | <parameter>peof</parameter> points to. |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 376 | </para> |
| 377 | |
| 378 | <para> |
C. Scott Ananian | 6b86e85 | 2007-07-15 23:41:13 -0700 | [diff] [blame] | 379 | The <parameter>data</parameter> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 380 | parameter can be used to create a single call back function for |
| 381 | several files, see <xref linkend="usingdata"/>. |
| 382 | </para> |
| 383 | |
| 384 | <para> |
C. Scott Ananian | 6b86e85 | 2007-07-15 23:41:13 -0700 | [diff] [blame] | 385 | The rest of the parameters and the return value are described |
| 386 | by a comment in <filename>fs/proc/generic.c</filename> as follows: |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 387 | </para> |
| 388 | |
C. Scott Ananian | 6b86e85 | 2007-07-15 23:41:13 -0700 | [diff] [blame] | 389 | <blockquote> |
| 390 | <para> |
| 391 | You have three ways to return data: |
| 392 | </para> |
| 393 | <orderedlist> |
| 394 | <listitem> |
| 395 | <para> |
| 396 | Leave <literal>*start = NULL</literal>. (This is the default.) |
| 397 | Put the data of the requested offset at that |
| 398 | offset within the buffer. Return the number (<literal>n</literal>) |
| 399 | of bytes there are from the beginning of the |
| 400 | buffer up to the last byte of data. If the |
| 401 | number of supplied bytes (<literal>= n - offset</literal>) is |
| 402 | greater than zero and you didn't signal eof |
| 403 | and the reader is prepared to take more data |
| 404 | you will be called again with the requested |
| 405 | offset advanced by the number of bytes |
| 406 | absorbed. This interface is useful for files |
| 407 | no larger than the buffer. |
| 408 | </para> |
| 409 | </listitem> |
| 410 | <listitem> |
| 411 | <para> |
| 412 | Set <literal>*start</literal> to an unsigned long value less than |
| 413 | the buffer address but greater than zero. |
| 414 | Put the data of the requested offset at the |
| 415 | beginning of the buffer. Return the number of |
| 416 | bytes of data placed there. If this number is |
| 417 | greater than zero and you didn't signal eof |
| 418 | and the reader is prepared to take more data |
| 419 | you will be called again with the requested |
| 420 | offset advanced by <literal>*start</literal>. This interface is |
| 421 | useful when you have a large file consisting |
| 422 | of a series of blocks which you want to count |
| 423 | and return as wholes. |
| 424 | (Hack by Paul.Russell@rustcorp.com.au) |
| 425 | </para> |
| 426 | </listitem> |
| 427 | <listitem> |
| 428 | <para> |
| 429 | Set <literal>*start</literal> to an address within the buffer. |
| 430 | Put the data of the requested offset at <literal>*start</literal>. |
| 431 | Return the number of bytes of data placed there. |
| 432 | If this number is greater than zero and you |
| 433 | didn't signal eof and the reader is prepared to |
| 434 | take more data you will be called again with the |
| 435 | requested offset advanced by the number of bytes |
| 436 | absorbed. |
| 437 | </para> |
| 438 | </listitem> |
| 439 | </orderedlist> |
| 440 | </blockquote> |
| 441 | |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 442 | <para> |
| 443 | <xref linkend="example"/> shows how to use a read call back |
| 444 | function. |
| 445 | </para> |
| 446 | </sect1> |
| 447 | |
| 448 | |
| 449 | |
| 450 | |
Rob Landley | 9de476b | 2008-02-07 00:13:31 -0800 | [diff] [blame] | 451 | <sect1 id="Writing_data"> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 452 | <title>Writing data</title> |
| 453 | |
| 454 | <para> |
| 455 | The write call back function allows a userland process to write |
| 456 | data to the kernel, so it has some kind of control over the |
| 457 | kernel. The write function should have the following format: |
| 458 | </para> |
| 459 | |
| 460 | <funcsynopsis> |
| 461 | <funcprototype> |
| 462 | <funcdef>int <function>write_func</function></funcdef> |
| 463 | <paramdef>struct file* <parameter>file</parameter></paramdef> |
| 464 | <paramdef>const char* <parameter>buffer</parameter></paramdef> |
| 465 | <paramdef>unsigned long <parameter>count</parameter></paramdef> |
| 466 | <paramdef>void* <parameter>data</parameter></paramdef> |
| 467 | </funcprototype> |
| 468 | </funcsynopsis> |
| 469 | |
| 470 | <para> |
| 471 | The write function should read <parameter>count</parameter> |
| 472 | bytes at maximum from the <parameter>buffer</parameter>. Note |
| 473 | that the <parameter>buffer</parameter> doesn't live in the |
| 474 | kernel's memory space, so it should first be copied to kernel |
| 475 | space with <function>copy_from_user</function>. The |
| 476 | <parameter>file</parameter> parameter is usually |
| 477 | ignored. <xref linkend="usingdata"/> shows how to use the |
| 478 | <parameter>data</parameter> parameter. |
| 479 | </para> |
| 480 | |
| 481 | <para> |
| 482 | Again, <xref linkend="example"/> shows how to use this call back |
| 483 | function. |
| 484 | </para> |
| 485 | </sect1> |
| 486 | |
| 487 | |
| 488 | |
| 489 | |
| 490 | <sect1 id="usingdata"> |
| 491 | <title>A single call back for many files</title> |
| 492 | |
| 493 | <para> |
| 494 | When a large number of almost identical files is used, it's |
| 495 | quite inconvenient to use a separate call back function for |
| 496 | each file. A better approach is to have a single call back |
| 497 | function that distinguishes between the files by using the |
| 498 | <structfield>data</structfield> field in <structname>struct |
| 499 | proc_dir_entry</structname>. First of all, the |
| 500 | <structfield>data</structfield> field has to be initialised: |
| 501 | </para> |
| 502 | |
| 503 | <programlisting> |
| 504 | struct proc_dir_entry* entry; |
| 505 | struct my_file_data *file_data; |
| 506 | |
| 507 | file_data = kmalloc(sizeof(struct my_file_data), GFP_KERNEL); |
| 508 | entry->data = file_data; |
| 509 | </programlisting> |
| 510 | |
| 511 | <para> |
| 512 | The <structfield>data</structfield> field is a <type>void |
| 513 | *</type>, so it can be initialised with anything. |
| 514 | </para> |
| 515 | |
| 516 | <para> |
| 517 | Now that the <structfield>data</structfield> field is set, the |
| 518 | <function>read_proc</function> and |
| 519 | <function>write_proc</function> can use it to distinguish |
| 520 | between files because they get it passed into their |
| 521 | <parameter>data</parameter> parameter: |
| 522 | </para> |
| 523 | |
| 524 | <programlisting> |
| 525 | int foo_read_func(char *page, char **start, off_t off, |
| 526 | int count, int *eof, void *data) |
| 527 | { |
| 528 | int len; |
| 529 | |
| 530 | if(data == file_data) { |
| 531 | /* special case for this file */ |
| 532 | } else { |
| 533 | /* normal processing */ |
| 534 | } |
| 535 | |
| 536 | return len; |
| 537 | } |
| 538 | </programlisting> |
| 539 | |
| 540 | <para> |
| 541 | Be sure to free the <structfield>data</structfield> data field |
| 542 | when removing the procfs entry. |
| 543 | </para> |
| 544 | </sect1> |
| 545 | </chapter> |
| 546 | |
| 547 | |
| 548 | |
| 549 | |
| 550 | <chapter id="tips"> |
| 551 | <title>Tips and tricks</title> |
| 552 | |
| 553 | |
| 554 | |
| 555 | |
| 556 | <sect1 id="convenience"> |
| 557 | <title>Convenience functions</title> |
| 558 | |
| 559 | <funcsynopsis> |
| 560 | <funcprototype> |
| 561 | <funcdef>struct proc_dir_entry* <function>create_proc_read_entry</function></funcdef> |
| 562 | <paramdef>const char* <parameter>name</parameter></paramdef> |
| 563 | <paramdef>mode_t <parameter>mode</parameter></paramdef> |
| 564 | <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef> |
| 565 | <paramdef>read_proc_t* <parameter>read_proc</parameter></paramdef> |
| 566 | <paramdef>void* <parameter>data</parameter></paramdef> |
| 567 | </funcprototype> |
| 568 | </funcsynopsis> |
| 569 | |
| 570 | <para> |
| 571 | This function creates a regular file in exactly the same way |
| 572 | as <function>create_proc_entry</function> from <xref |
| 573 | linkend="regularfile"/> does, but also allows to set the read |
| 574 | function <parameter>read_proc</parameter> in one call. This |
| 575 | function can set the <parameter>data</parameter> as well, like |
| 576 | explained in <xref linkend="usingdata"/>. |
| 577 | </para> |
| 578 | </sect1> |
| 579 | |
| 580 | |
| 581 | |
Rob Landley | 9de476b | 2008-02-07 00:13:31 -0800 | [diff] [blame] | 582 | <sect1 id="Modules"> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 583 | <title>Modules</title> |
| 584 | |
| 585 | <para> |
| 586 | If procfs is being used from within a module, be sure to set |
| 587 | the <structfield>owner</structfield> field in the |
| 588 | <structname>struct proc_dir_entry</structname> to |
| 589 | <constant>THIS_MODULE</constant>. |
| 590 | </para> |
| 591 | |
| 592 | <programlisting> |
| 593 | struct proc_dir_entry* entry; |
| 594 | |
| 595 | entry->owner = THIS_MODULE; |
| 596 | </programlisting> |
| 597 | </sect1> |
| 598 | |
| 599 | |
| 600 | |
| 601 | |
Rob Landley | 9de476b | 2008-02-07 00:13:31 -0800 | [diff] [blame] | 602 | <sect1 id="Mode_and_ownership"> |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 603 | <title>Mode and ownership</title> |
| 604 | |
| 605 | <para> |
| 606 | Sometimes it is useful to change the mode and/or ownership of |
| 607 | a procfs entry. Here is an example that shows how to achieve |
| 608 | that: |
| 609 | </para> |
| 610 | |
| 611 | <programlisting> |
| 612 | struct proc_dir_entry* entry; |
| 613 | |
| 614 | entry->mode = S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH; |
| 615 | entry->uid = 0; |
| 616 | entry->gid = 100; |
| 617 | </programlisting> |
| 618 | |
| 619 | </sect1> |
| 620 | </chapter> |
| 621 | |
| 622 | |
| 623 | |
| 624 | |
| 625 | <chapter id="example"> |
| 626 | <title>Example</title> |
| 627 | |
| 628 | <!-- be careful with the example code: it shouldn't be wider than |
| 629 | approx. 60 columns, or otherwise it won't fit properly on a page |
| 630 | --> |
| 631 | |
| 632 | &procfsexample; |
| 633 | |
| 634 | </chapter> |
| 635 | </book> |