Calling OS kernel syscalls from MicroPython

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
Post Reply
pfalcon
Posts: 1155
Joined: Fri Feb 28, 2014 2:05 pm

Calling OS kernel syscalls from MicroPython

Post by pfalcon » Fri Oct 19, 2018 9:32 pm

Made a quick example how to make a syscall into kernel of a Unix system: https://github.com/pfalcon/micropython- ... syscall.py . More specifically, the example is for Linux, but the man for helper function, syscall() says it was available since the original BSD Unix, so might work on the FreeBSD/NetBSD/OpenBSD too, though of course they use different syscall number.

This actually follows the footsteps of Lua's "ljsyscall" library, which I always thought was cool. But actually as you learn that it's done using the helper function from libc, the spell of magic disappears. Beyond that, it's just boring details of inconsistent syscall maps across different architectures of the same OS (Linux), and a bunch of structures to define. MicroPython can deal with all this, and as you learn the details, "developing libc in MicroPython" is much less useful, given that libc is already around. It still may be useful at times, for example Android's Bionic libc probably doesn't provide a lot of more advanced functions, and if they needed, knowing that there's a way to go directly to kernel for them is helpful. (Caveat: but does Bionic provide syscall() itself? D'oh!)

Code: Select all

# This demonstrates calling Linux syscalls "directly" (well, using libc
# proxy, but that appears to be "recommended" method anyway).
import ffilib
import uos


C = ffilib.libc()

# Different Linux archs have different syscall values (not like every one
# is different, but there're few "pattern", plus potentially any may add
# minor glitches on top of common pattern).
# Below are the numbers for x86_64, etc., but not for i386!
SYS_write = 1
SYS_getpid = 39

# Different syscalls have different signatures
syscall0 = C.func("l", "syscall", "i")
syscall_write = C.func("l", "syscall", "iiPi")


print("pid:", syscall0(SYS_getpid))

res = syscall_write(SYS_write, 1, "hello\n", 6)
print(res)
if res == -1:
    print("errno:", uos.errno())
Awesome MicroPython list
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/

Post Reply