Setting kernel tunable parameter - linux-kernel

As I wanted to introduce new kernel module parameter say new_param=1 /0 ,then after that parameter has to be checked inside kernel code as
if (new_param==1)
do some work.....
else
do other...
In this way I wanted to check by introducing new kernel module parameter.Can anyone please help me? What are the steps I need to follow to do this ?

One way to use a custom kernel parameter is to add it to the kernel command line and parse it out of /proc/cmdline, i.e.:
Add the parameter to the kernel command line
BOOT_IMAGE=<image> root=<root> ro quiet splash vt.handoff=7 your_parameter=<value>
When you boot, you will be able to access this parameter by parsing the contents of /proc/cmdline:
$ cat /proc/cmdline
BOOT_IMAGE=<image> root=<root> ro quiet splash vt.handoff=7 your_parameter=<value>
I believe a solution more tailored to your needs would include using __setup(), which is mentioned (but not explained well) in /Documentation/kernel-parameters.txt.
There are quite a few examples in the kernel source. One of such would be in /drivers/block/brd.c:
#ifndef MODULE
/* Legacy boot options - nonmodular */
static int __init ramdisk_size(char *str)
{
rd_size = simple_strtol(str, NULL, 0);
return 1;
}
__setup("ramdisk_size=", ramdisk_size);
#endif
Following this example, you could add your __init and __setup() in the relevant source file. For parsing integers from an option string in your __init function, see get_option() in /lib/cmdline.c
Update
For modules, you should use module_param(), which takes three arguments: variable name, variable type, sysfs permissions. More on the class is found at /linux/moduleparam.h.
In the module that you want to be able to pass parameters to, first declare the parameters as globals. An example usage would include the following in the module source:
int foo = 200;
module_param(foo, int, 0);
Recompile the module and you will see that you can load it via modprobe <module-name> foo=40.

Related

How to print source file name with dladdr() function?

I was trying to print a backtrace using dladdr(). info.dli_fname in the following code snippet is displaying the file name of an ELF file. Could you please tell me if it is possible to resolve and print the name of the source file and line number programmatically without the help of addr2line or gdb?
Code:
void print_caller(void)
{
int rc = -1;
Dl_info info = {0};
void *pc = __builtin_return_address(0);
rc = dladdr(pc, &info);
printf(" ==> %p: %s (in %s)\n", pc, info.dli_sname, info.dli_fname);
}
Output:
$ ./a.out
==> 0x55a6b04a1589: foo2 (in ./a.out)
tell me if it is possible to resolve and print the name of the source file and line number programmatically
It is definitely possible -- addr2line and gdb do that.
But it is very non-trivial -- it requires understanding and decoding (possibly multiple) complicated debugging info formats.
If you only care about a single platform (looks like Linux), things are a bit easier -- you only need to decode DWARF.
But that format is still pretty complicated. You should start with a helper library, such as libdwarf.

Autoconf: check struct member type

I am new to autoconf so I would ask you how could I check if a struct member is declared with a particular type.
For example I should check if struct posix_acl.a_refcount is declared as refcount_t and not atomic_t.
I know AC functions as ac_fn_c_check_decl and ac_fn_c_check_member, but none that accomplish this task.
Thank you!
Disclaimer: As there are no other answers at the time this answer is being written, this represents my best attempt to provide a solution, but you may need to adjust things to make it work for you. Caveat emptor.
You would need to use the AC_COMPILE_IFELSE macro with code that uses atomic_t, and if the compilation succeeds, then you're using atomic_t. As future-proofing, you might also add a test for refcount_t if the atomic_t test fails.
Example:
# _POSIX_ACL_REFCOUNT_T(type-to-check)
# ------------------------------------
# Checks whether the Linux kernel's `struct posix_acl'
# type uses `type-to-check' for its `a_refcount' member.
# Sets the shell variable `posix_acl_refcount_type' to
# `type-to-check' if that type is used, else the shell
# variable remains unset.
m4_define([_POSIX_ACL_REFCOUNT_T], [
AC_REQUIRE([AC_PROG_CC])
AC_MSG_CHECKING([whether struct posix_acl uses $1 for refcounts])
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE(
[#include <uapi/../linux/posix_acl.h>
struct posix_acl acl;
$1 v = acl.a_refcount;]
)],
[AC_MSG_RESULT([yes])
AS_VAR_SET([posix_acl_refcount_type], [$1])],
[AC_MSG_RESULT([no])
)
])
_POSIX_ACL_REFCOUNT_T([atomic_t])
# If posix_acl_refcount_type isn't set, see if it works with refcount_t.
AS_VAR_SET_IF([posix_acl_refcount_type],
[],
[_POSIX_ACL_REFCOUNT_T([refcount_t])]
)
dnl
dnl Add future AS_VAR_SET_IF tests as shown above for the refcount type
dnl before the AS_VAR_SET_IF below, if necessary.
dnl
AS_VAR_SET_IF([posix_acl_refcount_type],
[],
[AC_MSG_FAILURE([struct posix_acl uses an unrecognized type for refcounts])]
)
AC_DEFINE([POSIX_ACL_REFCOUNT_T], [$posix_acl_refcount_type],
[The type used for the a_refcount member of the Linux kernel's posix_acl struct.])
The tests assume that you already have a variable containing the kernel source directory, and the kernel source's include directory is specified in CPPFLAGS or CFLAGS prior to attempting the tests. You can add more tests at the position indicated, and if the resulting posix_acl_refcount_type shell variable is still not defined after all those tests, then the final AS_VAR_SET_IF invocation will invoke AC_MSG_FAILURE to stop configure with the specified error message.
Note that I used <uapi/../linux/posix_acl.h> to specifically target the kernel's linux/posix_acl.h header rather than the userspace API uapi/linux/posix_acl.h header installed in a system's include directory with the uapi/ stripped off, which may result in the compile tests above failing due to the missing struct posix_acl in the userspace API. This may not work the way I'd expect and may need modification.

Where does bash prompt escape sequence \h get the hostname from?

\h is a bash prompt escape sequence that expands to the hostname. Where does it get the hostname from? On my system it shows a value that I cannot find anywhere, not in hostname -f or /etc/hosts or /etc/hostname or /etc/sysconfig/network or $HOSTNAME. So I'm wondering where it's getting it from. My system is Centos 7.4. I know there are hidden places where things such as UUIDs are stored, and I seem to recall that I've come across a similar hidden hostname type of issue in the past, but I can't remember the details.
If you look at the bash source code you'll see in shell.c that it calls gethostname(2), a POSIX system call that retrieves the hostname from the kernel.
/* It's highly unlikely that this will change. */
if (current_host_name == 0)
{
/* Initialize current_host_name. */
if (gethostname (hostname, 255) < 0)
current_host_name = "??host??";
else
current_host_name = savestring (hostname);
}
This is not necessarily a canonical string. The kernel doesn't actually know the machine's network hostname. It just reports back whatever was passed to sethostname(2). To quote from the uname(2) man page:
On the other hand, the [hostname] is meaningless: it gives the name of the present machine in some undefined network, but typically machines are in more than one network and have several names. Moreover, the kernel has no way of knowing about such things, so it has to be told what to answer here.
On non-Linux systems without gethostname(2), bash falls back to uname(2). If uname(2) isn't even available then it simply displays "unknown". You can see that logic in lib/sh/oslib.c:
#if !defined (HAVE_GETHOSTNAME)
# if defined (HAVE_UNAME)
# include <sys/utsname.h>
int
gethostname (name, namelen)
char *name;
int namelen;
{
int i;
struct utsname ut;
--namelen;
uname (&ut);
i = strlen (ut.nodename) + 1;
strncpy (name, ut.nodename, i < namelen ? i : namelen);
name[namelen] = '\0';
return (0);
}
# else /* !HAVE_UNAME */
int
gethostname (name, namelen)
char *name;
int namelen;
{
strncpy (name, "unknown", namelen);
name[namelen] = '\0';
return 0;
}
# endif /* !HAVE_UNAME */
#endif /* !HAVE_GETHOSTNAME */
\h isn't updated if the hostname changes. The value is cached at startup when the shell is initialized.
[jkugelman#malkovich]$ hostname
malkovich
[jkugelman#malkovich]$ sudo hostname kaufman
[jkugelman#malkovich]$ hostname
kaufman
[jkugelman#malkovich]$ bash
[jkugelman#kaufman]
It probably (just a guess) uses the gethostname(2) system call (which is handled by the kernel, as all syscalls(2) are...)
BTW, GNU bash is (as most packages of your Linux distributions are) free software; so please download its source code and study it; use the source, Luke! and open the source more, please.
A more interesting question is how that information is cached by bash. Does it call gethostname at every command? You might also use strace(1) to find out.
Of course, take the habit of studying the source code of free software every time you are curious. And use strace -and the gdb debugger- to understand their dynamic behavior.
A French singer, G.Bedos, told us "La liberté ne s'use que si on ne s'en sert pas", that is
Freedom wears out if you don't use it.
(translation is mine, I am French but not a native English speaker)
So next time, please dive into the source code of free software. It is important to exercise your freedom, and that is what free software is about.

How do struct module works in kernel

I have written a interrupt driver linux version 3.8 for learning. I am using some gpio apis such as
gpio_request(gpioButton, "mypreciousss"); // Set up the gpioButton
When I saw inside this gpio_request it is using
if (!try_module_get(chip->owner))
here chip->owner is a struct module type variable.
gpio_request was the first function in my init function, and I did nothing to create struct module.
So how try_module_get can use one?
Here I am pasting the code snippet from function gpio_request() (linux 3.8)
desc = &gpio_desc[gpio];
chip = desc->chip;
if (chip == NULL)
goto done;
if (!try_module_get(chip->owner))
goto done;
Here, they are taking descriptor corresponding to passed GPIO, and that descriptor structure is used for further updates.

Julia: Having a function f() containing the macro #printf, how can I access the output outside f()?

In the Julia NMF package a verbose option provides information on convergence using the #printf macro.
How can I access this output without rewriting the NMF package io?
To rephrase, having a function f() containing the macro #printf, how can I access the output outside f()?
This does seem like useful functionality to have: I would suggest that you file an issue with the package.
However, as a quick hack, something like the following should work:
oldout = STDOUT
(rd,wr) = redirect_stdout()
start_reading(rd)
# call your function here
flush_cstdio()
redirect_stdout(oldout)
close(wr)
s = readall(rd)
close(rd)
s

Resources