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