TXT

Tips and tricks

By Danny Moore,2014-09-30 15:47
9 views 0
Tips and tricks

Tips and tricks

    Table of Contents

Convenience functions

    Modules

    Mode and ownership

    Convenience functions

    struct proc_dir_entry* create_proc_read_entry( const char* name,

     mode_t mode,

     struct proc_dir_entry* parent,

     read_proc_t* read_proc,

     void* data);

This function creates a regular file in exactly the same way as create_proc_entry

    from the section called “Creating a regular file” does, but also allows to set the

    read function read_proc in one call. This function can set the data as well, like

    explained in the section called “A single call back for many files”.

Modules

    If procfs is being used from within a module, be sure to set the owner field in the

    struct proc_dir_entry to THIS_MODULE.

struct proc_dir_entry* entry;

entry->owner = THIS_MODULE;

Mode and ownership

    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:

struct proc_dir_entry* entry;

    entry->mode = S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH; entry->uid = 0;

    entry->gid = 100;

    Chapter 5. Example/*

     * procfs_example.c: an example proc interface

     *

     * Copyright (C) 2001, Erik Mouw (J.A.K.Mouw@its.tudelft.nl)

     *

     * This file accompanies the procfs-guide in the Linux kernel

     * source. Its 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/), which is

     * 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/jiffies.h>

    #include <asm/uaccess.h>

#define MODULE_VERS "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, *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;

     len = sprintf(page, "jiffies = %ld\n",

     jiffies);

     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;

     /* DON'T DO THAT - buffer overruns are bad */

     len = sprintf(page, "%s = '%s'\n",

     fb_data->name, fb_data->value);

     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;

     if(count > FOOBAR_LEN)

     len = FOOBAR_LEN;

     else

     len = count;

     if(copy_from_user(fb_data->value, buffer, len))

     return -EFAULT;

     fb_data->value[len] = '\0';

     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 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_VERS);

     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_VERS); }

module_init(init_procfs_example);

    module_exit(cleanup_procfs_example);

MODULE_AUTHOR("Erik Mouw");

Report this document

For any questions or suggestions please email
cust-service@docsford.com