I am trying to make a DKM (Downloadable Kernel Module),"my_dkm.o", that I can load into a custom VxWorks kernel in run-time. I was able to make a simple one (it prints "hello world") but I want my DKM to invoke system calls that already exist within the kernel that is running.
From the shell, I can do -> syscallShow <my_group_#>,1 to give a list of the system calls I want to run. I can also invoke these system calls from the shell, but I don't know how to refer to them when developing my DKM.
Also, the Wind River Workbench help documentation only discusses invoking system calls from RTPs, which doesn't help because I am executing within kernel-space.
Thanks
In Short: You Don't
System call are exclusively to be used by RTPs to make a call to a function that resides in the kernel. The system call itself does a bit of housekeeping and then invokes the underlying kernel routine.
In the context of a DKM, since you are already in the kernel space, you simply need to invoke the same underlying kernel function as the system call.
Related
I was going through the Dinosaur book by Galvin where I faced the difficulty as asked in the question.
Typically application developers design programs according to an application programming interface (API). The API specifies a set of functions that are available to an application programmer, including the parameters that are passed to each function and the return values the programmer can expect.
The text adds that:
Behind the scenes the functions that make up an API typically invoke the actual system calls on behalf of the application programmer. For example, the Win32 function CreateProcess() (which unsurprisingly is used to create a new process) actually calls the NTCreateProcess() system call in the Windows kernel.
From the above two points I came to know that: Programmers using the API, make the function calls to the API corresponding to the system call which they want to make. The concerning function in the API then actually makes the system call.
Next what the text says confuses me a bit:
The run-time support system (a set of functions built into libraries included with a compiler) for most programming languages provides a system-call interface that serves as the link to system calls made available by the operating system. The system-call interface intercepts function calls in the API and invokes the necessary system calls within the operating system. Typically, a number is associated with each system call, and the system-call interface maintains a table indexed according to these numbers. The system call interface then invokes the intended system call in the operating-system kernel and returns the status of the system call and any return values.
The above excerpt makes me feel that the functions in the API does not make the system calls directly. There are probably function built into the system-call interface of the runtime support system, which are waiting for an event of system call from the function in the API.
The above is a diagram in the text explaining the working of the system call interface.
The text later explains the working of a system call in the C standard library as follows:
which is quite clear.
I don't totally understand the terminology of the excerpts you shared. Some terminology is also wrong like in the blue image at the bottom. It says the standard C library provides system call interfaces while it doesn't. The standard C library is just a standard. It is a convention. It just says that, if you write a certain code, then the effect of that code when it is ran should be according to the convention. It also says that the C library intercepts printf() calls while it doesn't. This is general terminology which is confusing at best.
The C library doesn't intercept calls. As an example, on Linux, the open source implementation of the C standard library is glibc. You can browse it's source code here: https://elixir.bootlin.com/glibc/latest/source. When you write C/C++ code, you use standard functions which are specified in the C/C++ convention.
When you write code, this code will be compiled to assembly and then to machine code. Assembly is also a higher level representation of machine code. It is just closer to the actual code as it is easier to translate to it then C/C++. The easiest case to understand is when you compile code statically. When you compile code statically, all code is included in your executable. For example, if you write
#include <stdio.h>
int main() {
printf("Hello, World!");
return 0;
}
the printf() function is called in stdio.h which is a header provided by gcc written specifically for one OS or a set of UNIX-like OSes. This header provides prototypes which are defined in other .c files provided by glibc. These .c files provide the actual implementation of printf(). The printf() function will make a system call which rely on the presence of an OS like Linux to run. When you compile statically, the code is all included up to the system call. You can see my answer here: Who sets the RIP register when you call the clone syscall?. It specifically explains how system calls are made.
In the end you'll have something like assembly code pushing some arguments into some conventionnal registers then the actual syscall instruction which jumps to an MSR. I don't totally understand the mechanism behind printf() but it will jump to the Linux kernel's implementation of the write system call which will write to the console and return.
I think what confuses you is that the "runtime-support system" is probably referring to higher level languages which are not compiled to machine code directly like Python or Java. Java has a virtual machine which translates the bytecode produced by compilation to machine code during runtime using a virtual machine. It can be confusing to not make this distinction when talking about different languages. Maybe your book is lacking examples.
From what I can find, .fini is used for the destruction of static storage duration objects after main returns. In a typical bare-metal application, main does not return. Is there any reason not to simply remove these symbols from the linker script?
In a typical bare-metal application, main does not return.
main() can indeed return to the startup code, which can be customized to do something after the application exited, e.g. restart it, cut the power, or start a firmware update. It that case, static destructors can be needed.
Is there any reason not to simply remove these symbols from the linker script?
If main() never returns and exit() is never called, then of course you can remove these symols, but then the library startup will miss them, and you'll have to provide a function to override the library function that iterates through __fini_array.
If you are using newlib, you can recompile it with --enable-lite-exit to omit all fini stuff.
Assuming that APIs are generally similar(and in some cases same) to the System Calls they invoke....
Does the fork() we invoke in our user application, a 'API in POSIX' which invokes the actual system call 'fork()'? Or do we directly invoke fork() system call?
And how does it compares to CreateProcess() in Win32 API.
Is CreateProcess() a system call which invokes another system call NTCreateProcess() system call OR Is CreateProcess() a function in the Win32 API which invokes NTCreateProcess() system call?
I can only speak for Linux and UNIX variants, but I imagine Windows is similar.
Does the fork() we invoke in our user application, a 'API in POSIX'
which invokes the actual system call 'fork()'? Or do we directly
invoke fork() system call?
In Linux, fork(2) is a syscall, but recent Linux versions don't use it in most cases. When you call fork(2) from a C user program, you're calling the glibc wrapper, not the real syscall - as of the latest version, the glibc wrapper invokes clone(2) and passes it the necessary flags to indicate the attributes of the new process. clone(2) is the real syscall (see man 2 clone).
However, even if you call clone(2) directly in a C program, you will be calling the glibc wrapper function. Most raw syscalls have an equivalent wrapper function in glibc because raw syscall invocation is architecture dependent.
Some manpages include the prototype for both, the wrapper and the raw syscall. For example, the manpage for clone(2) shows both variants:
SYNOPSIS
/* Prototype for the glibc wrapper function */
#include <sched.h>
int clone(int (*fn)(void *), void *child_stack,
int flags, void *arg, ...
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
/* Prototype for the raw system call */
long clone(unsigned long flags, void *child_stack,
void *ptid, void *ctid,
struct pt_regs *regs);
You can usually learn a lot from the manpages. man 2 fork mentions what I said above in the notes section:
NOTES
Under Linux, fork() is implemented using copy-on-write
pages, so the only penalty that it incurs is the time and memory
required to duplicate the parent's page tables, and to create a unique
task structure for the child.
Since version 2.3.3, rather than invoking the kernel's fork() system
call, the glibc fork() wrapper that is provided as part of the NPTL
threading implementation invokes clone(2) with flags that provide the
same effect as the traditional system call. (A call to fork() is
equivalent to a call to clone(2) specifying flags as just SIGCHLD.) The glibc wrapper invokes any fork handlers that
have been established using pthread_atfork(3).
(If you're wondering, NPTL stands for Native POSIX Threads Library)
TL;DR When you're programming, you never really invoke syscalls directly. You invoke the glibc wrappers that handle the nitty gritty details of raw syscall invocation.
As Jeffy Coffin pointed, API stands for Application Program Interface, and is a document that describes a set of functions, related types and other language interfaces and features for use by applications. An API can be pretty much anything. For example Stack Exchange has a web API that can be used by anything capable of making HTTP requests over the Internet.
Also, as Jerry Coffin said the term "system call" isn't very well defined. It just means an API function that implements an operating service. You could argue that neither CreateProcess nor NTCreateProcess are system calls. Both are C wrappers around the true system call, which is bit code written in assembly. On the other hand, I'd argue they're both system calls. They both offer access to the operating system's facility for creating new processes with no significant extra added functionality. Either way, it doesn't really matter.
I read that when you run module, the code becomes part of the kernel. But I figured that there can be context switch between processes while module's function is still executing. How could it be? I read that there are no context switches while in kernel.
Certainly there are context switches in the Linux kernel. It's called kernel pre-emption. I'm not sure where you read that there are no context-switches in the kernel or why you'd think it's impossible.
A kernel thread (presumably where your module code will be executing on) is scheduled just like any other user thread.
But the question seems incorrect.
But I figured that there can be context switch between processes while module's function is still executing.
What?
Say we have a module which implements a filesystem. If you open a file on such a filesystem through open syscall, the code goes open -> some lookups -> the code in the module. All of this is happening in the context of the same thread. There is no concept of module context. It may be the code in the module created some kernel threads on its own, but this has zero relation to it being a module.
process could run in one of these context at any given point of time :
user mode
kernel mode
Interrupt mode
Context switch happens in all cases. In Interrupt mode, it is programmer responsibility to disable context switch on the CPU while executing top half section of the interrupt. I dont know where you read that context switching do not happen in kernel mode.
I could not find any good document on internet about STM32 programming. STM's own documents do not explain anything more than register functions. I will greatly appreciate if anyone can explain my following questions?
I noticed that in all example programs that STM provides, local variables for main() are always defined outside of the main() function (with occasional use of static keyword). Is there any reason for that? Should I follow a similar practice? Should I avoid using local variables inside the main?
I have a gloabal variable which is updated within the clock interrupt handle. I am using the same variable inside another function as a loop condition. Don't I need to access this variable using some form of atomic read operation? How can I know that a clock interrupt does not change its value in the middle of the function execution? Should I need to cancel clock interrupt everytime I need to use this variable inside a function? (However, this seems extremely ineffective to me as I use it as loop condition. I believe there should be better ways of doing it).
Keil automatically inserts a startup code which is written in assembly (i.e. startup_stm32f4xx.s). This startup code has the following import statements:
IMPORT SystemInit
IMPORT __main
.In "C", it makes sense. However, in C++ both main and system_init have different names (e.g. _int_main__void). How can this startup code can still work in C++ even without using "extern "C" " (I tried and it worked). How can the c++ linker (armcc --cpp) can associate these statements with the correct functions?
you can use local or global variables, using local in embedded systems has a risk of your stack colliding with your data. with globals you dont have that problem. but this is true no matter where you are, embedded microcontroller, desktop, etc.
I would make a copy of the global in the foreground task that uses it.
unsigned int myglobal;
void fun ( void )
{
unsigned int myg;
myg=myglobal;
and then only use myg for the rest of the function. Basically you are taking a snapshot and using the snapshot. You would want to do the same thing if you are reading a register, if you want to do multiple things based on a sample of something take one sample of it and make decisions on that one sample, otherwise the item can change between samples. If you are using one global to communicate back and forth to the interrupt handler, well I would use two variables one foreground to interrupt, the other interrupt to foreground. yes, there are times where you need to carefully manage a shared resource like that, normally it has to do with times where you need to do more than one thing, for example if you had several items that all need to change as a group before the handler can see them change then you need to disable the interrupt handler until all the items have changed. here again there is nothing special about embedded microcontrollers this is all basic stuff you would see on a desktop system with a full blown operating system.
Keil knows what they are doing if they support C++ then from a system level they have this worked out. I dont use Keil I use gcc and llvm for microcontrollers like this one.
Edit:
Here is an example of what I am talking about
https://github.com/dwelch67/stm32vld/tree/master/stm32f4d/blinker05
stm32 using timer based interrupts, the interrupt handler modifies a variable shared with the foreground task. The foreground task takes a single snapshot of the shared variable (per loop) and if need be uses the snapshot more than once in the loop rather than the shared variable which can change. This is C not C++ I understand that, and I am using gcc and llvm not Keil. (note llvm has known problems optimizing tight while loops, very old bug, dont know why they have no interest in fixing it, llvm works for this example).
Question 1: Local variables
The sample code provided by ST is not particularly efficient or elegant. It gets the job done, but sometimes there are no good reasons for the things they do.
In general, you use always want your variables to have the smallest scope possible. If you only use a variable in one function, define it inside that function. Add the "static" keyword to local variables if and only if you need them to retain their value after the function is done.
In some embedded environments, like the PIC18 architecture with the C18 compiler, local variables are much more expensive (more program space, slower execution time) than global. On the Cortex M3, that is not true, so you should feel free to use local variables. Check the assembly listing and see for yourself.
Question 2: Sharing variables between interrupts and the main loop
People have written entire chapters explaining the answers to this group of questions. Whenever you share a variable between the main loop and an interrupt, you should definitely use the volatile keywords on it. Variables of 32 or fewer bits can be accessed atomically (unless they are misaligned).
If you need to access a larger variable, or two variables at the same time from the main loop, then you will have to disable the clock interrupt while you are accessing the variables. If your interrupt does not require precise timing, this will not be a problem. When you re-enable the interrupt, it will automatically fire if it needs to.
Question 3: main function in C++
I'm not sure. You can use arm-none-eabi-nm (or whatever nm is called in your toolchain) on your object file to see what symbol name the C++ compiler assigns to main(). I would bet that C++ compilers refrain from mangling the main function for this exact reason, but I'm not sure.
STM's sample code is not an exemplar of good coding practice, it is merely intended to exemplify use of their standard peripheral library (assuming those are the examples you are talking about). In some cases it may be that variables are declared external to main() because they are accessed from an interrupt context (shared memory). There is also perhaps a possibility that it was done that way merely to allow the variables to be watched in the debugger from any context; but that is not a reason to copy the technique. My opinion of STM's example code is that it is generally pretty poor even as example code, let alone from a software engineering point of view.
In this case your clock interrupt variable is atomic so long as it is 32bit or less so long as you are not using read-modify-write semantics with multiple writers. You can safely have one writer, and multiple readers regardless. This is true for this particular platform, but not necessarily universally; the answer may be different for 8 or 16 bit systems, or for multi-core systems for example. The variable should be declared volatile in any case.
I am using C++ on STM32 with Keil, and there is no problem. I am not sure why you think that the C++ entry points are different, they are not here (Keil ARM-MDK v4.22a). The start-up code calls SystemInit() which initialises the PLL and memory timing for example, then calls __main() which performs global static initialisation then calls C++ constructors for global static objects before calling main(). If in doubt, step through the code in the debugger. It is important to note that __main() is not the main() function you write for your application, it is a wrapper with different behaviour for C and C++, but which ultimately calls your main() function.