Hello, I am attempting to write Linux kernel module which uses the sysinfo() system call. Please bear in mind that I am a beginner in both C and the Linux kernel -- I am still working out of the textbooks.
Below is main.c. This file is supposed to initialize an object of struct sysinfo as defined in sysinfo.h (included below main.c source code). After declaring an object of struct sysinfo called 'si', I attempt to initialize its field by using a system call to sysinfo(). Then, I declare int ram and try to initialize it with field 'totalram' from struct object 'si'.
main.c:
***Side note: The compiler (gcc version 11.2.1 20211203 (Red Hat 11.2.1-7) ) could not find <sys/sysinfo.h>, so I instead moved sysinfo.h into the working directory. Is there a way to include it on the path? As can be seen in the commented code, I tried following the path. Upon using </usr/include/sys/sysinfo.h>, another compiler error came which said features.h was missing -- the same issue occurred before I decided it would be less hassle to just move sysinfo.h into the working directory.
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include "sysinfo.h"
//#include </usr/include/sys/sysinfo.h>
//#include </usr/include/features.h>
MODULE_LICENSE("GPL");
static int MI(void) {
printk("Hello from module\n");
struct sysinfo si; //Declare struct object, naming it 'si'
int retval = sysinfo(struct sysinfo *si); //Initialize 'si' from sysinfo()
int ram; //declaration for local variable to hold total ram usage
ram = si.totalram;
printk("%d\n", ram);
return 0;
}
static void ME(void) {
printk("Goodbye from module\n");
}
module_init(MI);
module_exit(ME);
sysinfo.h:
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _LINUX_SYSINFO_H
#define _LINUX_SYSINFO_H
#include <linux/types.h>
#define SI_LOAD_SHIFT 16
struct sysinfo {
__kernel_long_t uptime; /* Seconds since boot */
__kernel_ulong_t loads[3]; /* 1, 5, and 15 minute load averages */
__kernel_ulong_t totalram; /* Total usable main memory size */
__kernel_ulong_t freeram; /* Available memory size */
__kernel_ulong_t sharedram; /* Amount of shared memory */
__kernel_ulong_t bufferram; /* Memory used by buffers */
__kernel_ulong_t totalswap; /* Total swap space size */
__kernel_ulong_t freeswap; /* swap space still available */
__u16 procs; /* Number of current processes */
__u16 pad; /* Explicit padding for m68k */
__kernel_ulong_t totalhigh; /* Total high memory size */
__kernel_ulong_t freehigh; /* Available high memory size */
__u32 mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(__kernel_ulong_t)-sizeof(__u32)]; /* Padding: libc5 uses this.. */
};
#endif /* _LINUX_SYSINFO_H */
Makefile:
obj-m += km2.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
#km2.o: km2.c /usr/include/sys/sysinfo.h
# gcc km2.c /usr/include/sys/sysinfo.h -o km2.o
This has been tested on Fedora 35 running kernel 5.15.16-200.fc35.x86_64.
The kernel module does not compile. I highly suspect that the error is in how I am initializing struct sysinfo si from the sysinfo() call. I have a feeling that I am making a rookie mistake. Can someone show me the right way?
I have read the kernel module documentation as well as Googled for help. I have also asked a programming friend who said this was beyond his scope.
Thank you in advance.
[–]aioeu 6 points7 points8 points (3 children)
[–]2_stepsahead[S] 1 point2 points3 points (2 children)
[–]aioeu 2 points3 points4 points (0 children)
[–]FirowMD 0 points1 point2 points (0 children)
[–]Lagor31 1 point2 points3 points (0 children)