kernel module write to proc - c

I have made the following kernel module to create a process "hello_proc" in /proc directory:
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
static int hello_proc_show(struct seq_file *m, void *v) {
seq_printf(m, "P5 : Hello proc!\n");
return 0;
}
static int hello_proc_open(struct inode *inode, struct file *file) {
return single_open(file, hello_proc_show, NULL);
}
static const struct file_operations hello_proc_fops = {
.owner = THIS_MODULE,
.open = hello_proc_open,
.read = seq_read,
.write = seq_write,
.llseek = seq_lseek,
.release = single_release,
};
static int hello_proc_init(void) {
proc_create("hello_proc", 0, NULL, &hello_proc_fops);
printk("P5 : Process hello proc created");
return 0;
}
static void hello_proc_exit(void) {
remove_proc_entry("hello_proc", NULL);
}
MODULE_LICENSE("GPL");
module_init(hello_proc_init);
module_exit(hello_proc_exit);
I inserted the module and a proc file "hello_proc" was created successfully in directory /proc. The next thing I want to do is to write the output of command:
ls -l -t /proc | head -21 > /proc/hello_proc
to file "hello_proc" followed by reading as well. When I do (as root):
root#anubhav-Inspiron-3421:~$ ls -l -t /proc | head -21 > /proc/hello_proc
the execution just stops.
Now, I checked a lot of codes and resources on internet, but could not find one that explains how to write to a proc file. No resource on youtube either.
The best thing I found for writing to proc file were codes that were creating proc files using function "create_proc_entry", which looked fairly simple but for an older kernel version, different than mine. Any suggestions/directions to move ahead.

seq_write doesn't do what you might think. It's actually like seq_printf except it just writes a fixed number of bytes (rather than formatted outpuut). The seq_xxx API doesn't support writing to the device. You have to implement that separately.
For a fairly simple model of how to create a writable device using single_open on the read side, take a look at proc_pid_set_comm_operations, which implements /proc/<pid>/comm and also supports writing.
Also, note that create_proc_entry was deprecated but it's pretty straight-forward to change create_proc_entry to proc_create. As described in Documentation/filesystems/seq_file.txt:
- entry = create_proc_entry("sequence", 0, NULL);
- if (entry)
- entry->proc_fops = &ct_file_ops;
+ entry = proc_create("sequence", 0, NULL, &ct_file_ops);

Related

It seems my _PG_init() doesn't get called when the module loads

I am trying to write a small extension for PostgreSQL.
As a way to test if my module loads correctly I am writing some stuff in files in the void _PG_init(void) and void _PG_fini(void) functions. Here is the code of these two functions:
#include "postgres.h"
#include "executor\executor.h"
#include "fmgr.h"
#include "funcapi.h"
#include <stdio.h>
PG_MODULE_MAGIC;
extern void _PG_init(void);
extern void _PG_fini(void);
static void myExecutorStart(QueryDesc *queryDesc, int eflags);
static void myExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count);
static void myExecutorFinish(QueryDesc *queryDesc);
static void myExecutorEnd(QueryDesc *queryDesc);
static ExecutorStart_hook_type prevExecutorStart = NULL;
static ExecutorRun_hook_type prevExecutorRun = NULL;
static ExecutorFinish_hook_type prevExecutorFinish = NULL;
static ExecutorEnd_hook_type prevExecutorEnd = NULL;
void _PG_init(void) {
FILE *file = NULL;
file = fopen("F:\\init.txt", "a+");
fprintf(file, "Init started!\n");
fclose(file);
prevExecutorStart = ExecutorStart_hook;
ExecutorStart_hook = myExecutorStart;
prevExecutorRun = ExecutorRun_hook;
ExecutorRun_hook = myExecutorRun;
prevExecutorFinish = ExecutorFinish_hook;
ExecutorFinish_hook = myExecutorFinish;
prevExecutorEnd = ExecutorEnd_hook;
ExecutorEnd_hook = myExecutorEnd;
}
void _PG_fini(void) {
FILE *file = NULL;
file = fopen("F:\\fini.txt", "a+");
fprintf(file, "Fini started!\n");
fclose(file);
ExecutorStart_hook = prevExecutorStart;
ExecutorRun_hook = prevExecutorRun;
ExecutorFinish_hook = prevExecutorFinish;
ExecutorEnd_hook = prevExecutorEnd;
}
Those functions are in a file called "myextension.c", compiled into "myextension.dll". I built it in Visual Studio 2015, with following settings:
Configuration Properties -> General, “Configuration Type” = “Dynamic
Library (.dll)”.
C/C++ -> Code Generation, “Enable C++ Exceptions” = “No”,“Advanced”
set “Compile As” = “Compile as C Code (/TC)”.
Linker -> Manifest File, “Generate Manifest” = “No”.
Linker -> Input -> Additional Dependencies, added “postgres.lib” to the
library list.
Configuration Properties -> C/C++ -> General, Additional Include
Directories, added: “include\server\port\win32_msvc”, “include\server\port\win32”, “include\server”, “include”
Solution configuration = Release
Solution Platform = x64 (Installed 64 bit version of PostgreSQL 9.6 on
Windows 10)
In myExecutorXXX functions I check if there are previous ExecutorXXX functions, call them if they exist, if they don't I call the standard_ExecutorXXX function. Here is an example of one of the functions:
static void myExecutorStart(QueryDesc *queryDesc, int eflags) {
if (prevExecutorStart) prevExecutorStart(queryDesc, eflags);
else standard_ExecutorStart(queryDesc, eflags);
FILE *file = NULL;
file = fopen("F:\\query.txt", "a+");
fprintf(file, "Query: %s started!\n", queryDesc->sourceText);
fclose(file);
}
I copied the "myextension.dll" in "../PostgreSQL/9.6/lib" directory, and added a "myextension.control" and "myextension--1.0.sql" to "../PostgreSQL/9.6/share/extension" directory.
myextension.control:
# pg_extension extension
comment = 'myextension!!!'
default_version = '1.0'
myextension--1.0.sql:
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION myextension" to load this file. \quit
In the "postgresql.conf" I added shared_preload_libraries = 'myextension'. After that I connected to a test DB and ran: CREATE EXTENSION myextension;, and restarted the server.
If anyone has any idea what might be causing this, please help.
A couple of comments to get you on the right track:
_PG_fini() will never get called, because modules don't get unloaded.
_PG_init(), however, does get called when the module is loaded. Your main question seems to be why nothing is written to F:\init.txt and other files you use for logging.
On Windows, PostgreSQL normally runs as service. I suspect that the operating system user doesn't have the privileges to write to these files. I know little about Windows and its permission management, but I notice that you do not check the return code of fopen(), so it might well have silently failed.
My recommendation is to use the logging infrastructure instead, e.g. with
elog(LOG, "Init started!");
That will write the message to the PostgreSQL server log and is much more comfortable and less error prone.
Two more comments:
There is no point in creating an extension, because your code does not provide any SQL functions. CREATE EXTENSION myextension is a no-operation.
Don't forget to restart the PostgreSQL server after changing shared_preload_libraries.

Configure Parameters of LED Trigger from Kernel Space

I'm working on an embedded project. Our board is using Linux kernel v3.16.7. I'm working on supporting a couple of peripheral LEDs that monitor activity. I've successfully modified the boot procedure to load the drivers and create sysfs entries in /sys/class/leds/, which is great. I've also attached a oneshot trigger to the leds so I can echo 1 > shot from within /sys/class/leds/actled1\:green/ and the led blinks. Exactly what I want.
However, I want to configure the delays for each LED when I instantiate the driver during boot, and I'm not clear on how to do that. The driver creates sysfs entries in /sys/class/leds/actled1\:green/ called delay_on and delay_off, and I can write to them from userspace to configure the delays, but it should be possible to set their initial values from from kernel space during instantiation. I also want to be able to set the invert parameter (which is just another sysfs entry just like the delays).
How can I configure the parameters of an led trigger when I instantiate the driver from kernel space?
Below is how I instantiate the LED GPIOs. First I set up the structs required:
static struct gpio_led my_leds[] __initdata = {
{
.name = "actled1:green",
.default_trigger = "oneshot"
.gpio = ACTIVITY_LED_GPIO_BASE + 0,
.active_low = true,
},
{
.name = "actled2:red",
.default_trigger = "oneshot"
.gpio = ACTIVITY_LED_GPIO_BASE + 1,
.active_low = true,
},
};
static struct gpio_led_platform_data my_leds_pdata __initdata = {
.num_leds = ARRAY_SIZE(my_leds),
.leds = my_leds,
};
Then, I call this function to create the platform devices:
static int __init setup_my_leds (void)
{
struct platform_device *pdev;
int ret;
pdev = platform_device_alloc("leds-gpio", -1);
if (!pdev) {
return -ENOMEM;
}
ret = platform_device_add_data(pdev,
&my_leds_pdata,
sizeof(my_leds_pdata));
if (ret < 0) {
platform_device_put(pdev);
return ret;
}
ret = platform_device_add(pdev);
if (ret < 0) {
platform_device_put(pdev);
return ret;
}
return 0;
}
The definition for the gpio_led struct is in include/linux/leds.h line 327, and the definition for gpio_led_platform_data is in line 341 of the same file. The definition of platform_device_add_data is in drivers/base/platform.c line 284.
It may be useful to look at the source for the oneshot trigger (drivers/leds/trigger/ledtrig-oneshot.c) in order to answer the question. Also relevant is the "leds-gpio" driver (drivers/leds/leds-gpio.c).
I suspect the answer is somewhere in drivers/base/platform.c and the associated documentation, but I'm not seeing any functions that deal with the data I need.
To address some of the information that I inadvertently left out:
the boot loader sets the kernel arguments, and we can't modify the boot loader. that's fine; the values i want to set are constants and i can hard-code them in.
the driver is baked into the kernel at compile time (and, i presume, loaded by the bootloader) rather than loading a .ko with modprobe later.
i would love a general way to set arbitrary trigger parameters, not only oneshot's delay_on / delay_off. for example, oneshot's invert parameter.
i'm totally fine modifying oneshot / creating new triggers. in fact, once i get it working with oneshot, i'll need to create a new trigger that expands upon oneshot (which is also the reason i need to set arbitrary parameters).
There are a few issues and I think I've found the solutions, but even though you provided a good deal of info, there were some things missing, so I'll enumerate for all possible scenarios, so be patient ...
(1) Getting the initial values you want to set. I presume you have already figured this out, but ... You can get these from kernel cmdline parsing (e.g. you add the values to /boot/grub2/grub.cfg as myleds.delay_on=.... If you're loading via modprobe, you set a module parameter. These could also be a config file as in myleds.config_file=/etc/sysconfig/myleds.conf
(2) You could set them inside your setup_my_leds [except for the recalcitrance of oneshot_trig_activate--which we'll deal with soon enough]. From drivers/base/platform.c:
/**
* arch_setup_pdev_archdata - Allow manipulation of archdata before its used
* #pdev: platform device
*
* This is called before platform_device_add() such that any pdev_archdata may
* be setup before the platform_notifier is called. So if a user needs to
* manipulate any relevant information in the pdev_archdata they can do:
*
* platform_device_alloc()
* ... manipulate ...
* platform_device_add()
*
* And if they don't care they can just call platform_device_register() and
* everything will just work out.
*/
So, with that in mind, let's change your setup function slightly:
static int __init setup_my_leds (void)
{
struct platform_device *pdev;
int ret;
// get initial values you want to set, possibly storing away for later use
my_leds_get_init_values(...);
pdev = platform_device_alloc("leds-gpio", -1);
if (!pdev) {
return -ENOMEM;
}
// Choice (1): set your initial values in my_leds_pdata here
my_leds_set_init_values(&my_leds_pdata);
// NOTE: just does kmemdup and sets pdev->dev.platform_data
ret = platform_device_add_data(pdev,
&my_leds_pdata,
sizeof(my_leds_pdata));
if (ret < 0) {
platform_device_put(pdev);
return ret;
}
// Choice (2): set your initial values in pdev->dev.platform_data here
my_leds_set_init_values(pdev->dev.platform_data);
ret = platform_device_add(pdev);
if (ret < 0) {
platform_device_put(pdev);
return ret;
}
return 0;
}
(3) Unfortunately, since you're using .default_trigger = "oneshot", the above data will get blasted by oneshot_trig_activate in drivers/leds/trigger/ledtrig-oneshot.c. So, we need to deal with that.
Option (A): Assuming you can rebuild the whole kernel as you choose, just modify oneshot_trig_activate in ledtrig-oneshot.c and remove the the lines that use DEFAULT_DELAY. This is only really useful if you know that it's not used by anything else in your system that might need the default values.
Option (B): If you're not allowed to modify ledtrig-oneshot.c, but are allowed to add new triggers to drivers/leds/trigger, copy the file to (e.g.) ledtrig-oneshot2.c and do the changes there. You'll need to change the .name to .name = "oneshot2". The easy way [in vi, of course :-)] is :%s/oneshot/oneshot2/g. You'll also need to add a new entry in the Kconfig and Makefile for this. Then, change your struct definition to use the new driver: .default_trigger = "oneshot2"
Option (C): Assuming you can't [or don't want to] touch the drivers/leds/trigger directory, copy ledtrig-oneshot.c to your driver directory [renaming as appropriate]. Do the edits from option (B) above there. With some trickery in your Makefile, you can get it to build both my_led_driver.ko and ledtrig-oneshot2.ko. You'll need modify your Kconfig, possibly adding a depends on LED_TRIGGERS for the led trigger driver. You could also put the two into separate subdirectories and the individual Makefile/Kconfig might be simpler: my_led/my_driver and my_led/my_trigger
Option (C) would be more work up front, but might be cleaner and more portable in the long run. Of course, you could do option (A) for proof-of-concept, then do option (B), and do the "final ship" as option (C).
An alternate way for when you set the initial values: Remember the comment for my_leds_get_init_values was possibly storing away for later use. You could change oneshot2_trig_activate to call it instead of using DEFAULT_DELAY. I don't like this quite as much and prefer the solutions that simply neuter oneshot_trig_activate's offensive behavior. But, with some testing, you may find that this is the way you have to do it.
Hopefully, the above will work. If not, edit your question with additional info and/or restrictions [and send me a comment], and I'll be glad to update my answer [I've been doing drivers for 40+].
UPDATE: Okay, herein is a fully annotated and modified LED trigger driver that you can use as a drop in replacement for drivers/led/trigger/ledtrig-oneshot.c.
Because the invert parameter can not be passed directly through any standard struct you have access to in your setup function [i.e. it's stored in a private struct inside the trigger driver], remove the "Choice (1)" and "Choice (2)". We'll set them all at once inside the [modified] oneshot_trig_activate.
Also, the init parameters you want must be set up and stored as globals by the my_leds_get_init_values so the trigger driver can find them. That is, there is no way to do this cleanly (e.g. with a pointer to a private struct that gets passed around) as the structs you have access to in setup don't have a field for this. See the top part of the trigger driver for discussion on this.
My first step was to annotate the base driver with descriptive comments. There were no comments in it, except for K&R style for copyright and a single one-liner. My annotations are ANSI ("//") comments.
If I were taking over the driver, I would add these and leave them in. However, my level of comments might be considered "over-commenting" according to the kernel style guide and might be considered "cruft", particularly for a driver that is this straightforward.
Next step was to add the necessary changes. All places that have additions/changes are marked with a comment block that starts with "C:". These are the important places to look. Note that these comments are legitimate candidates to leave in. In other more complex drivers, the level of commenting is up to the author. The "C:" is just to highlight the places for you.
With the annotations, a straight line read through might be easier now. Also, a diff -u might also help. If you've got everything under git, so much the better.
Because of all this, I'd remove the "Option (A)" [direct modification of the original file] and do "Option (B)" or "Option (C)" only.
The trigger driver uses all static definitions, so the global edit I suggested before is not needed. I did do .name = "myled_oneshot";, so you'll need to match that with .default_trigger = "myled_oneshot";. Feel free to use my_leds_whatever to be consistent with your existing naming convention. When I do this for myself, I usually use my initials, so it becomes ce_leds_whatever--YMMV
Anyway, here's the entire modified trigger driver. Note that I've done the editing, but I've not tried to compile/build it.
/*
* One-shot LED Trigger
*
* Copyright 2012, Fabio Baltieri <fabio.baltieri#gmail.com>
*
* Based on ledtrig-timer.c by Richard Purdie <rpurdie#openedhand.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/ctype.h>
#include <linux/slab.h>
#include <linux/leds.h>
#include "../leds.h"
// C: we need to get access to the init data populated by the setup function
// we have the "clean way" with a struct definition inside a header file and
// the "dirty way" using three separate int globals
// in either case, the externs referenced here must be defined in the "my_leds"
// driver as global
// C: the "clean way"
// (1) requires that we have a path to the .h (e.g. -I<whatever)
// (2) this would be easier/preferable for the "Option (C)"
// (3) once done, easily extensible [probably not a consideration here]
#ifdef MYLED_USESTRUCT
#include "whatever/myled_init.h"
extern struct myled_init myled_init;
// C: the "ugly way"
// (1) no need to use a separate .h file
// (2) three separate global variables is wasteful
// (3) more than three, and we really should consider the "struct"
#else
extern int myled_init_delay_on;
extern int myled_init_delay_off;
extern int myled_init_invert;
#endif
#define DEFAULT_DELAY 100
// oneshot trigger driver private data
struct oneshot_trig_data {
unsigned int invert; // current invert state
};
// arm oneshot sequence from sysfs write to shot file
static ssize_t led_shot(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
led_blink_set_oneshot(led_cdev,
&led_cdev->blink_delay_on, &led_cdev->blink_delay_off,
oneshot_data->invert);
/* content is ignored */
return size;
}
// show invert state for "cat invert"
static ssize_t led_invert_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
return sprintf(buf, "%u\n", oneshot_data->invert);
}
// set invert from sysfs write to invert file (e.g. echo 1 > invert)
static ssize_t led_invert_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
unsigned long state;
int ret;
ret = kstrtoul(buf, 0, &state);
if (ret)
return ret;
oneshot_data->invert = !!state;
if (oneshot_data->invert)
led_set_brightness_async(led_cdev, LED_FULL);
else
led_set_brightness_async(led_cdev, LED_OFF);
return size;
}
// show delay_on state for "cat delay_on"
static ssize_t led_delay_on_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
}
// set delay_on from sysfs write to delay_on file (e.g. echo 20 > delay_on)
static ssize_t led_delay_on_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
unsigned long state;
int ret;
ret = kstrtoul(buf, 0, &state);
if (ret)
return ret;
led_cdev->blink_delay_on = state;
return size;
}
// show delay_off state for "cat delay_off"
static ssize_t led_delay_off_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
}
// set delay_off from sysfs write to delay_off file (e.g. echo 20 > delay_off)
static ssize_t led_delay_off_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
unsigned long state;
int ret;
ret = kstrtoul(buf, 0, &state);
if (ret)
return ret;
led_cdev->blink_delay_off = state;
return size;
}
// these are the "attribute" definitions -- one for each sysfs entry
// pointers to these show up in the above functions as the "attr" argument
static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
static DEVICE_ATTR(delay_off, 0644, led_delay_off_show, led_delay_off_store);
static DEVICE_ATTR(invert, 0644, led_invert_show, led_invert_store);
static DEVICE_ATTR(shot, 0200, NULL, led_shot);
// activate the trigger device
static void oneshot_trig_activate(struct led_classdev *led_cdev)
{
struct oneshot_trig_data *oneshot_data;
int rc;
// create an instance of the private data we need
oneshot_data = kzalloc(sizeof(*oneshot_data), GFP_KERNEL);
if (!oneshot_data)
return;
// save the pointer in the led class struct so it's available to other
// functions above
led_cdev->trigger_data = oneshot_data;
// attach the sysfs entries
rc = device_create_file(led_cdev->dev, &dev_attr_delay_on);
if (rc)
goto err_out_trig_data;
rc = device_create_file(led_cdev->dev, &dev_attr_delay_off);
if (rc)
goto err_out_delayon;
rc = device_create_file(led_cdev->dev, &dev_attr_invert);
if (rc)
goto err_out_delayoff;
rc = device_create_file(led_cdev->dev, &dev_attr_shot);
if (rc)
goto err_out_invert;
// C: this is what the driver used to do
#if 0
led_cdev->blink_delay_on = DEFAULT_DELAY;
led_cdev->blink_delay_off = DEFAULT_DELAY;
#endif
led_cdev->activated = true;
// C: from here to the return is what the modified driver must do
#ifdef MYLED_USESTRUCT
led_cdev->blink_delay_on = myled_init.delay_on;
led_cdev->blink_delay_off = myled_init.delay_off;
oneshot_data->invert = myled_init.invert;
#else
led_cdev->blink_delay_on = myled_init_delay_on;
led_cdev->blink_delay_off = myled_init_delay_off;
oneshot_data->invert = myled_init_invert;
#endif
// C: if invert is off, nothing to do -- just like before
// if invert is set, we implement this as if we just got an instantaneous
// write to the sysfs "invert" file (which would call led_invert_store
// above)
// C: this is a direct rip-off of the above led_invert_store function which
// we can _not_ call here directly because we don't have access to the
// data it needs for its arguments [at least, not conveniently]
// so, we extract the one line we actually need
if (oneshot_data->invert)
led_set_brightness_async(led_cdev, LED_FULL);
return;
// release everything if an error occurs
err_out_invert:
device_remove_file(led_cdev->dev, &dev_attr_invert);
err_out_delayoff:
device_remove_file(led_cdev->dev, &dev_attr_delay_off);
err_out_delayon:
device_remove_file(led_cdev->dev, &dev_attr_delay_on);
err_out_trig_data:
kfree(led_cdev->trigger_data);
}
// deactivate the trigger device
static void oneshot_trig_deactivate(struct led_classdev *led_cdev)
{
struct oneshot_trig_data *oneshot_data = led_cdev->trigger_data;
// release/destroy all the sysfs entries [and free the private data]
if (led_cdev->activated) {
device_remove_file(led_cdev->dev, &dev_attr_delay_on);
device_remove_file(led_cdev->dev, &dev_attr_delay_off);
device_remove_file(led_cdev->dev, &dev_attr_invert);
device_remove_file(led_cdev->dev, &dev_attr_shot);
kfree(oneshot_data);
led_cdev->activated = false;
}
/* Stop blinking */
led_set_brightness(led_cdev, LED_OFF);
}
// definition/control for trigger device registration
// C: changed the name to "myled_oneshot"
static struct led_trigger oneshot_led_trigger = {
.name = "myled_oneshot",
.activate = oneshot_trig_activate,
.deactivate = oneshot_trig_deactivate,
};
// module init function -- register the trigger device
static int __init oneshot_trig_init(void)
{
return led_trigger_register(&oneshot_led_trigger);
}
// module exit function -- unregister the trigger device
static void __exit oneshot_trig_exit(void)
{
led_trigger_unregister(&oneshot_led_trigger);
}
module_init(oneshot_trig_init);
module_exit(oneshot_trig_exit);
MODULE_AUTHOR("Fabio Baltieri <fabio.baltieri#gmail.com>");
MODULE_DESCRIPTION("One-shot LED trigger");
MODULE_LICENSE("GPL");
As you can see in ledtrig-oneshot.c, the delay is always initialized with DEFAULT_DELAY. Unfortunately, if you want to be able to configure a different value at startup, this is a mechanism you will have to implement..
As Craig answered it should be from kernel command line options, but there could be a problem with embedded systems where the boot-loader passes the command line parameters and the boot-loaders cannot be modified, they are usually OTP . In that case I see only 2 options
hard coding in the kernel init function
as mac address is stored in eeprom for the nic driver to read, if the values can be stored in a flash (nor) and the value read on boot. This can be done after creating the mtd partitions during kernel boot.

Getting the actual executable path of current process context - Linux kernel

I'm trying to get the actual executable path of a running process through my kernel driver.
I've done the following:
static struct kretprobe do_fork_probe = {
.entry_handler = (kprobe_opcode_t *) process_entry_callback,
.handler = (kprobe_opcode_t *) NULL,
.maxactive = 1000,
.data_size = 0
};
do_fork_probe.kp.addr = (kprobe_opcode_t*)kallsyms_lookup_name("do_fork");
if ((ret = register_kretprobe(&do_fork_probe)) < 0)
return -1;
static int process_entry_callback(struct kretprobe_instance *ri, struct pt_regs *regs)
{
printk("Executable path = %s\n", executable_path(current));
return 0;
}
The executable_path function:
char* executable_path(struct task_struct* process)
{
#define PATH_MAX 4096
char* p = NULL, *pathname;
struct mm_struct* mm = current->mm;
if (mm)
{
down_read(&mm->mmap_sem);
if (mm->exe_file)
{
pathname = kmalloc(PATH_MAX, GFP_ATOMIC);
if (pathname)
p = d_path(&mm->exe_file->f_path, pathname, PATH_MAX);
}
up_read(&mm->mmap_sem);
}
return p;
}
The problem is that if I run an executable using bash as follows:
./execname
I'm getting the following output:
Executable path = /bin/bash
While what I really want is the : execname (Actually its full path but lets start with the name)
Any suggestions?
It is unclear what you try to get, so here are list of options:
execname as it is considered by SystemTap. Simple process->comm should suffice. That is how comm field defined in Kernel:
char comm[TASK_COMM_LEN]; /* executable name excluding path
- access with [gs]et_task_comm (which lock
it with task_lock())
- initialized normally by setup_new_exec */
But if bash is a symlink, than comm should contain symlink's name, not the real executable name.
argv[0] first element of command line arguments array as it seen my application (and may be altered by it). There is a get_cmdline() function in kernel, but it seem not to be exported.
Basename of full path. In this case, do not call d_path, just take d_name field of dentry:
strlcpy(pathname, mm->exe_file->f_path->d_name, PATH_MAX);
But it sounds like a XY problem. You trying to get executable names for all forking processes? Why not use SystemTap directly?
# stap -v -e 'probe scheduler.process_fork { println(execname()); }'

EXT3 file operations

I am trying to follow how Linux deals with EXT3 files.
I am looking at fs/ext3/file.c where there are file operations that deal with the files are present:
const struct file_operations ext3_file_operations = {
.llseek = generic_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.aio_read = generic_file_aio_read,
.aio_write = generic_file_aio_write,
.unlocked_ioctl = ext3_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext3_compat_ioctl,
#endif
.mmap = generic_file_mmap,
.open = dquot_file_open,
.release = ext3_release_file,
.fsync = ext3_sync_file,
.splice_read = generic_file_splice_read,
.splice_write = generic_file_splice_write,
};
How can I find when does .open is replaced by the function "dquot_file_open" for example?
Should I follow the system call defined in fs/open.c:
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
Or should I be looking at other functions?
I am working on Linux 3.7.6 for User-Mode-Linux
The Linux kernel is organized in an OOP manner (though written in C). The struct file_operations is really a class, the members (function pointers) are the function members ("methods" for Java heads) of the class. The code you quote serves to set up the ext3 object by filling in the function pointers. This is done at compile/link time.
The open(2) system call calls this indirectly, by finding out the struct file_operations relevant for the file system at hand, and calling its open member.
I'd suggest you take a look at the kernelnewbies page for an overall view and more detailed help.

How do I create a "netlink" between kernel and userspace?

I want to use netlink to communicate between an application and kernel space. My Linux kernel version is 2.6.28, and the following is my wrong code:
nf_sock=netlink_kernel_create(NL_PROTO,0,nl_user_skb,THIS_MODULE);
The abbreviated error message is:
error: too few arguments to function 'netlink_kernel_create'
In the file <linux/netlink.h>, the function netlink_kernel_create() is defined as
extern struct sock *netlink_kernel_create(struct net *net,int unit,unsigned int groups,void (*input)(struct sk_buff *skb),struct mutex *cb_mutex,struct module *module)
I don't understand what to use for the first argument, net. Can someone explain what I should use here?
A struct net contains information about the network namespace, a set of network resources available to processes. Note that there could be multiple network namespaces (i.e. multiple instances of the networking stack), but most drivers use the init_net namespace.
Your call should probably look something like the following
nf_sock = netlink_kernel_create(&init_net,
NETLINK_USERSOCK,
0,
nl_rcv_func,
NULL,
THIS_MODULE);
where nl_rcv_func is a function taking struct sk_buff *skb as the only argument and processes the received netlink message.
You seem to have been following a guide such as this one, which (being from 2005) might well have been outpaced by the development of the kernel. It seems the internal API to create a netlink from the kernel side has changed.
Either check the Documentation/ folder in your local kernel tree for some (hopefully fresher) documentation, or read the code itself. You could also trawl the Linux Kernel mailing list archives for any mention of the changes that seem to have happened.
Here is the actual implemntation as of 2.6.29, if you'd rather puzzle it out backwards (and haven't already checked this in your own tree, of course).
Yes, struct net is indeed for net namespace, but it is not proper to always use init_net, you should register your own pernet_operations, like this:
static struct pernet_operations fib_net_ops = {
.init = fib_net_init,
.exit = fib_net_exit,
};
static int __net_init fib_net_init(struct net *net)
{
int error;
#ifdef CONFIG_IP_ROUTE_CLASSID
net->ipv4.fib_num_tclassid_users = 0;
#endif
error = ip_fib_net_init(net);
if (error < 0)
goto out;
error = nl_fib_lookup_init(net);
if (error < 0)
goto out_nlfl;
error = fib_proc_init(net);
if (error < 0)
goto out_proc;
out:
return error;
out_proc:
nl_fib_lookup_exit(net);
out_nlfl:
ip_fib_net_exit(net);
goto out;
}
static int __net_init nl_fib_lookup_init(struct net *net)
{
struct sock *sk;
struct netlink_kernel_cfg cfg = {
.input = nl_fib_input,
};
sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, &cfg);
if (sk == NULL)
return -EAFNOSUPPORT;
net->ipv4.fibnl = sk;
return 0;
}
and finally:
register_pernet_subsys(&fib_net_ops);
I would suggest ioctl for kernel/user communication. The ioctl interface is standard and the chance of been updated between kernels is small.

Resources