Overview
liblitmus is the userspace library of LITMUSRT. When you compile liblitmus, a static library file named liblitmus.a is created. Userspace applications can and should link against this library like any other shared library.
When creating userspace test tools, it may be tempting to create new tools within the liblitmus repository. However, this is not recommended as it is difficult to maintain when newer liblitmus versions become available. Instead, project-specific userspace tools should be maintained in separate repositories and explicitly link against liblitmus.
To simplify this setup, liblitmus generates an include file (at $LIBLITMUS/inc/config.makefile) that is intended to be used in the Makefiles of projects that depend on liblitmus. The following tutorial shows how to use these include files.
Tutorial
In the following, we assume that you want to create a tool that depends on the LITMUSRT userspace interface.
The tutorial assumes that you have checked out and compiled liblitmus to a directory $DIR/liblitmus (where $DIR is arbitrary).
Step 1: Create a New Directory
Create a new directory in $DIR, say $DIR/mytools/, and create a sub-directory $DIR/mytools/src/.
$ cd $DIR
$ mkdir -p mytools/src
Step 2: Create a Source File
For testing purposes, we'll create a simple dummy app that links against liblitmus. To this end, create a file mytool.c in mytools/src with the following contents.
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 /* include the main liblitmus header */
5 #include <litmus.h>
6
7
8 int main(int argc, char** argv)
9 {
10 struct rt_task param;
11 int ready_rt_tasks, all_rt_tasks;
12
13 init_litmus();
14 init_rt_task_param(¶m);
15
16 /* Normally you would configure the task here, enter real-time mode, and start
17 * the real-time computation, but we'll simply call a liblitmus function and
18 * quit here as the goal is simply to test whether we can successfully link
19 * against liblitmus.
20 */
21
22 /* query the LITMUS^RT proc interface */
23 if (!read_litmus_stats(&ready_rt_tasks, &all_rt_tasks)) {
24 perror("read_litmus_stats");
25 exit(1);
26 }
27
28 printf("There are %d real-time tasks waiting for a synchronous "
29 "task system release.\n", ready_rt_tasks);
30 printf("There are %d real-time tasks in total.\n", all_rt_tasks);
31
32 return 0;
33 }
Step 3: Create a Makefile
Next, we'll setup the new project to link against liblitmus by reusing the build framework of liblitmus.
To this end, create a Makefile in mytools/ with the following contents.
1 # ##############################################################################
2 # User variables
3
4 # user variables can be specified in the environment or in the local make.conf file
5 -include make.conf
6
7 # Where is the LITMUS^RT userspace library source tree?
8 # By default, we assume that it resides in a sibling directory named 'liblitmus'.
9 LIBLITMUS ?= ../liblitmus
10
11 # Include default configuration from liblitmus.
12 # IMPORTANT: Liblitmus must have been built before this file exists.
13 include ${LIBLITMUS}/inc/config.makefile
14
15 # all sources
16 vpath %.c src/
17
18 # local include files
19 CPPFLAGS += -Iinclude/
20
21 # ##############################################################################
22 # Targets
23
24 all = mytool
25
26 .PHONY: all clean
27 all: ${all}
28 clean:
29 rm -f ${all} *.o *.d
30
31 obj-mytool = mytool.o
32 mytool: ${obj-mytool}
33
34
35 # dependency discovery
36 include ${LIBLITMUS}/inc/depend.makefile
37
This completes the setup.
Testing
You should now be able to compile mytool and link against liblitmus, which should look similar to this.
$ make
/usr/bin/gcc -O2 -Wall -Werror -g -Wdeclaration-after-statement -D_XOPEN_SOURCE=600 -D_GNU_SOURCE -m64 -DARCH=x86_64 -I../liblitmus/include -I../liblitmus/arch/x86/include -I../liblitmus/arch/x86/include/uapi -I../liblitmus/arch/x86/include/generated/uapi -Iinclude/ -c -o mytool.o src/mytool.c
/usr/bin/gcc -m64 mytool.o -L../liblitmus -llitmus -o mytool
You should now be able to run ./mytool.
$ file mytool
mytool: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
On a non-LITMUSRT kernel, you'll see a bunch of error messages because the task initialization fails.
$ ./mytool
mlockall(): Cannot allocate memory
Warning: Could not initialize LITMUS^RT, mlockall() failed.
init_kernel_iface: cannot open LITMUS^RT control page (No such file or directory)
kernel <-> user space interface initialization: No such file or directory
Warning: Could not initialize LITMUS^RT, kernel <-> user space interface initialization failed.
read_litmus_stats: No such file or directory
On a LITMUSRT kernel, the tool should run without error messages if executed as root.
Adding Additional Build Targets
To add additional build targets, you can simply add them to the all list.
For example, suppose you wanted to add a second application called myapp, and further suppose that myapp also needs to link against librt (Linux's POSIX real-time library) to get access to clock_gettime(). This can be realized with the following steps:
Add a target myapp to all. This should look now like: all = mytool myapp
Add -lrt to LDLIBS, like this: LDLIBS += -lrt. It's important that you use += (and not =) to ensure that the settings of liblitmus are not removed.
Add the list obj-myapp to list all object files needed for myapp. For example: obj-myapp = myapp.o if there is a file mytools/src/myapp.c
Add the target for myapp, like this: myapp: ${obj-myapp}.
As a result, the Makefile should now look as follows.
1 [...]
2 # ##############################################################################
3 # Targets
4
5 all = mytool myapp
6
7 LDLIBS += -lrt
8
9 .PHONY: all clean
10 all: ${all}
11 clean:
12 rm -f ${all} *.o *.d
13
14 obj-mytool = mytool.o
15 mytool: ${obj-mytool}
16
17 obj-myapp = myapp.o
18 myapp: ${obj-myapp}
19
20 [...]
Cleanup
The makefile automatically includes a clean target to remove all build products.
$ make clean
rm -f mytool myapp *.o *.d
Discussion
The method described in this tutorial is the preferred way to link against liblitmus, as it prevents the accumulation of cruft in liblitmus. Even though liblitmus already contains a bunch of tools in bin/, it should not accumulate further project-specific tools and applications. Further, it ensures that clients of liblitus are compiled with compatible flags.
If you use a cross-compiler to build liblitmus (e.g., to build binaries for an ARM target), then any project using /inc/config.makefile will by default also be built using the cross-compiler. In our experience, this simplifies cross-compilation setups considerably.
Optionally including the local file make.conf (which doesn't have to exist) makes it possible include local settings that are never committed to git. It's not strictly needed, but if you plan on collaborating with others (who, for example, might have checked out liblitmus at a different path), this is a useful feature and we recommend that you always provide this functionality in LITMUSRT-related Makefiles.