阅读视图

发现新文章,点击刷新页面。
🔲 ☆

WIP side channels {meltdown, spectre}

This is WIP write-up.


§ praise LLM!

While playing with spectre V2 side channel, I found an issue and LLM helped me to solve it in no time, that would otherwise cost me a lot of sanity.

A shared memory between the victim and attacker processes is used as a probe array to exploit cache flush/reload timing attack

I tried two differnet methods of creating it:

  1. a file-backed shared memory:

    int fd = open("shared_file", O_RDWR);
    void *shared_mem = mmap((addr, size, pflags, MAP_SHARED, fd, 0);
    
  2. Sys V SHM

    key_t key = ftok("keyfile", 'A');
    int shmid = shmget(key, size, IPC_CREAT | 0666);
    void *shared_mem = shmat(shmid, addr, 0);
    

The spectre V2 attack with method 1. is consistantly better than with 2.

Here is the take away:

  • (seemingly the prominent factor: swap and reclaim behaviour.

    #include <sys/mman.h>
    mlock(addr, len); // after attaching
    
  • Sys V shm defaults to THP (transparent huge page); kernel may promote 4K pages to 2MB huge pages, see while file backed shared memory is not subject to THP unless specified. To toggle this behaviour
    System wide:

    echo never | sudo tee /sys/kernel/mm/transparent_hugepage/shmem_enabled
    

    Per process:

    #include <sys/prctl.h>
    prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0);
    

    Per allocation (call after shmat:

    #include <sys/mman.h>
    madvise(addr, length, MADV_NOHUGEPAGE);
    
🔲 ☆

Agentic Society and Its Future

A blunt reference, but I immediately thought about Kaczynski 1 when the idea randomly jumped into my mind.

There is no doubt that coding agents lower the gate-keeping bar for making useful programs. They are powerful tools that tremendously boost the productivity for those who know what they are doing. Language models understand a legacy codebase better than the most experienced employee; and No, I don’t advocate for a human-purism that only handwritten code are acceptable. This post is not even concerned about the “AI takes my job” narrative.

In fancy words, the coding agent is a tool of the future that is retrofitted into conventions of the past. Today, we are asking agents to “do a human’s job,” like writing programs in a high-level language, whose semantics still resemble ours, because those languages are made for humans.

We distinguish between two kinds of technology, which we will call small-scale technology and organization-dependent technology. Small-scale technology is technology that can be used by small-scale communities without outside assistance. Organization-dependent technology is technology that depends on large-scale social organization

TWO KINDS OF TECHNOLOGY

Which kind of technology is Programming, then? Or, more generally, the interface and skills needed to operate the machinery that belongs to the second kind?

The science of computing started long before the engineering of computing; that’s why German uses Informatiker.


The text received some polishing from ai-powered proofreader. Ha Ha Ha.


  1. Kaczynski, Industrial Society and Its Future; For sure, I condemn his terrorism acts. ↩︎

🔲 ☆

checklist for learning programming language

§ the language

  • keywords
  • primitive types
    • integer, float, string, array, slice, pointer…
    • numerics
    • boolean & operators
  • composite types (class, struct …)
  • control-flow: if, switch-case, while, for
  • variable: type, allocation, mutability, lifetime, static, const, scope, atomic
  • function declaration: type, inline, lambda…

§ the runtime

  • garbage collection
  • stacktrace

§ standard library

  • io, file, format and log
  • networking
  • crypto (?)

§ package management and module system

§ toolchain and build system

  • compiling unit and linking
🔲 ☆

Synchronisationbegriffe - WIP

Entschuldigung für mein kaputtes Deutsch. :)

Die Hauptfrage ist, was die Anforderungen für eine korrekte Synchronisationsimplementierung (z.B. eines Locks) sind?

Es gilt die Regel, dass zwei Dinge erfüllt sind, nämlich Sicherheit und Lebendigkeit. Dass problem ist jedoch, dass diese Dinge oft mit unterschiedlichen Begriffen und Kategorisierungen difiniert werden, besonders whenn es darum geht, die englische und deutsche Literatur abzugleischen.

Sicherheit (Wechselseitiger Ausschluss / Mutual Exclusion)

  • Koodinierung der Abläufe der beteiligten Prozesse, sodass die kritischen Abschnitte jeweils nur von einem Prozess betreten werden können.1
  • Consider N computers, each engaged in a process which, for our aims, can be regarded as cyclic. In each of the cycles a so-caled “critical section” occurs and the computers have to be programmed in such a way that at any moment only one of these N cyclic processes is in its critical section.2

  1. Vorlesung Betriebssysteme und Sicherheit, TU Dresden, OS. ↩︎

  2. E. W. Dijkstra. 1965. Solution of a problem in concurrent programming control. Commun. ACM 8, 9 (Sept. 1965), 569.
    https://doi.org/10.1145/365559.365617 ↩︎

🔲 ☆

process, thread, task

§ general [2]

Tanenbaum:

A process is just an instance of an executing program, including the current values of the program counter, registers, and variables. Conceptually, each process has its own virtual CPU.

§ linux specific [1]

§ difference between process and thread

§ process group

§ reference

  • [1] W. Mauerer, “Linux® Kernel Architecture”.
  • [2] A. S. Tanenbaum and H. Bos, Modern operating systems, 4. ed. Boston: Prentice Hall, 2015.
🔲 ☆

The Nucleus of a Multiprogramming System

Per Brinch Hansen, The nucleus of a multiprogramming system.1 ;pretty much the paper the started microkernels … but it’s not a microkernel itself

Abstract:

This paper describes the philosophy and structure of a multiprogramming system that can be extended with a hierarchy of operating systems to suit diverse requirements of program scheduling and resource allocation. The system nucleus simulates an environment in which program execution and input/output are handled uniformly as parallel, cooperating processes. A fundamental set of primitives allows the dynamic creationg and control ofa hierarchy of processes as well as the communication among them.

The purpose of the system nucleus is to implement these fundamental concepts: simulation of processes; communi- cation among processes; creation, control, and removal of processes.

§§ “precise meaning” to the process concept

  • distinction between internal (~=program execution) and external processes (I/O).

§§ synchronization primitives and IPC

  • semaphore alone does suffice (safety and efficiency)
  • message buffering within system nucleus as basic means of IPC.
  • system nucleus adminsters a common pool of message buffers and message queue for each process.
  • IPC primitives:
    // note Fortran, in/out parameters; you have to guess :)
    send_message(receiver, message, buffer), // block/non-block (queued buffers)
    wait_message(sender, message, buffer),   // blocks
    send_answer(result, answer, buffer),     // non-block
    wait_answer(result, answer, buffer),     // blocks
    

send_message copies a message into the first available buffer within the pool and delivers it in the queue of a named receiver. The receiver is activated if it is waiting for a message. The sender continues after being informed of the identity of the message buffer.

wait_message delays the requesting process until a message arrives in its queue. When the process is allowed to proceed, it is supplied with the name of the sender, the contents of the message, and the identity of the message buffer. The buffer is removed from the queue and made ready to transmit an answer.

send_answer copies an answer into a buffer in which a message has been received and delivers it in the queue of the original sender. The sender of the message is activated if it is waiting for the answer. The answering process continues immediately

wait_answer delays the requesting process until an answer arrives in a given buffer. On arrival, the answer is copied into the process and the buffer is returned to the pool. The result specifies whether the answer is a response from another process or a dummy answer generated by the system nucleus in response to a message addressed to a nonexisting process.

  • regard the selection of a buffer as the creation of an identification of a conversation

  • the buffer (communication channel) is protected and exclusive to the pair.

  • queued messages undisturbed on the removal of their sender processes. Nucleus returns buffers to pool when answered.

  • (reverse: ) on removal of a process, systems check for unanswered messages sent to the process and return dummy answers to the sender.

  • it’s always the client who pays for the resource (i.e. buffer) during IPC. server only needs to reply (reusing sender buffer) instead of allocating one of its own

§§ dynamic creation, control and removal of processes


difference to actual microkernel (I mean, l4re)?

  • parent has full control over its (direct?) children (the mandated hierarchy doesn’t seem to be micro-kernel-ish)
  • every process can talk to each other (same namespace?)
  • address space isolation? paging?
  • async IPC (vs. l4)
  • not yet the “capability” concept
  • global buffer pool, instead of UTCB

  1. Per Brinch Hansen. 1970. The nucleus of a multiprogramming system. Commun. ACM 13, 4 (April 1970), 238–241. https://doi.org/10.1145/362258.362278 ↩︎

🔲 ☆

GNU toolchains

§§ every damn single GNU toolchain binary

NOTE:

<m>     - placeholder for machine tuple e.g. x86_64-linux-gnu
<v>   - placeholder for toolchain (gcc) version

GCC, under /usr/bin; Sometimes they are prefixed with machine tuples. Archlinux is x86_64 exclusive, therefore the prefixes are not necessary.

And, gcc seemingly overlaps binutils. Some of those are wrappers (see below)

From binutils:

compile stuffs:---
as              the assembler
ld              the linker. ld.bfd and ld.gold are two different
                implementation of ld. ld points to either of them
ld.bfd          "Binary File Descriptor". The older one. More support
                and compatability
ld.gold         "Gold". Newer, faster linker
objcopy         copy and translate object files / bin formats

combine stuffs:---
ar              handle archives;
                mostly, combine .o files into single .a
                linker could extract desired .o from .a
dwp             conbine DWARF object files (dwo) into single package
ranlib          generate index into archive

poke stuffs:------
strip           remove symbols, debug info etc. from obj files
elfedit         update header and program property of elf files

print stuffs:-----
objdump         display info about object files + dissambly
readelf         display info about elf files
addr2line       addr or symbol+offset into file + line number
c++filt         demangle c++ (and java) symbols
nm              list symbols from object files (+sizes)
size            list section size and total size of binary
strings         show printable chars in files

From gcc:


The "frontend" under /usr/bin
They are the user-facing programs that you may call directly

gcc             the GNU compiler "collection" all-in-one tool
cc              alias to (or same as) gcc
c89, c99        gcc wrappers with std=c89/99

g++             gcc with c++
c++             alias to (or same as) g++

cpp             C preprocessor

gcc-ar          wrapper of ar w/ --plugin=/../liblto_plugin.so
gcc-nm          wrapper of nm w/ liblto plugin
gcc-ranlib      wrapper of ranlib w/ liblto plugin

gcov            coverage testing tool
gcov-tool       offline gcda profile processing tool


The "backends" under /usr/lib/gcc/<m>/<v>/
They are internal binaries called by tools like gcc. You don't call it directly

cc1             the C Compiler
cc1plus         the C++ Compiler
collect2        wrapper of ld (from binutils); also wrapps around lto?
lto1            collect2 invokes it if -flto is enabled (indirectly via ld?)
lto-wrapper     called by collect2 ...  (ok this is twisted...but I won't worry
                about this level of "details")

Also check gcc/Makefile (configure first)

§§ misc:

Also gprof stuffs from binutils

gprof stuffs:

gp-archive
gp-collect-app
gp-display-html
gp-display-src
gp-display-text
gprof
gprofng
gprofng-archive
gprofng-collect-app
gprofng-display-html
gprofng-display-src
gprofng-display-text

comments from gcc/collect2.cc

/* !!! When GCC calls collect2, it does not know whether it is calling collect2
 *  or ld. So collect2 cannot meaningfully understand any options except those ld
 *  understands. If you propose to make GCC pass some other option, just imagine
 *  what will happen if ld is really ld!!!
*/
🔲 ☆

C Runtime

Mixing content from:


crt0.o / crt*.o the startup objects

Historically crt0.o (C Runtime Zero). Modern toolchains split crt0 and use crt1.o (the primary startup object).

  • crt1.o : entry point; provides _start symbol
  • crti.o : initialization; prologues of .init and .finit sections
  • crtn.o : termination; epilogue of .init and .finit sections

crt1 Variants

  • Scrt1.o : used in place of crt1.o to generate PIEs
  • gcrt1.o : used in place of crt1.o to generate profiling info. (see gprof)
  • Mcrt1.o : like gcrt1.o; for prof; useless on Linux
  • grcrt1.o, rcrt1.o : wtf

C++ constructor stuffs, I guess

  • crtbegin{,S,T}.o to find start of constructors (gcc); S for shared objects/PIEs. T for static executables.
  • crtend{,S}.o : find start of destructors (gcc);

Instead of function calls, the startup objects are concatenated at link time.

General linking order:

crt1.o crti.o crtbegin.o [-L paths] [user objects] [gcc libs] [C libs] [gcc libs] crtend.o crtn.o

typical file locations

  • /usr/lib/{Scrt1, crt1, crti, crtn, gcrt1}.o
  • /lib64/gcc/<m>/<v>/ : crtbegin, crtend , etc.

notes

entry point + crt1.o / crt0.o
  • The crt0 / crt1 provides the entry point _start for the binary loader.

initialization + crti.o

  • stack initialization, if not done by the kernel
  • set up memory (data, BSS)
  • prepare argc, argv for main
  • invoking constructors for global/static objects (C++)
  • library initialization
  • then calls main(argc, argv, envp)

cleanup + crtn.o

  • when main returns, calls OS exit routines (e.g. _exit)
$ readelf -s /usr/lib/crt1.o 
Num: Value  Size  Type   Bind   Vis      Ndx Name
 0: [...]    0   NOTYPE  LOCAL  DEFAULT  UND 
 1: [...]    0   SECTION LOCAL  DEFAULT    1 .text
 2: [...]    5   FUNC    GLOBAL HIDDEN     1 _dl_relocate_sta[...]
 3: [...]   38   FUNC    GLOBAL DEFAULT    1 _start
 4: [...]    0   NOTYPE  GLOBAL DEFAULT  UND main
 5: [...]    0   NOTYPE  WEAK   DEFAULT   11 data_start
 6: [...]    4   OBJECT  GLOBAL DEFAULT    3 _IO_stdin_used
 7: [...]    0   NOTYPE  GLOBAL DEFAULT  UND __libc_start_main
 8: [...]    0   NOTYPE  GLOBAL DEFAULT   11 __data_start

$ readelf -s /usr/lib/crti.o 
Symbol table '.symtab' contains 4 entries:
Num: Value  Size  Type   Bind   Vis      Ndx Name
 0: [...]    0   NOTYPE  LOCAL  DEFAULT  UND 
 1: [...]    0   NOTYPE  WEAK   DEFAULT  UND __gmon_start__
 2: [...]    0   FUNC    GLOBAL HIDDEN     5 _init
 3: [...]    0   FUNC    GLOBAL HIDDEN     7 _fini
🔲 ☆

the GNU autosomething

Those who do not understand Autoconf are condemned to reinvent it, poorly.

I doubt that…

§ notes on autoconf: fuck my life!

(copied from GNU documents)

Files used in preparing a software package for distribution, when using just Autoconf:

{your source files} --> [autoscan*] --> [configure.scan] --> configure.ac

configure.ac --.
               |   .------> autoconf* -----> configure
[aclocal.m4] --+---+
               |   `-----> [autoheader*] --> [config.h.in]
[acsite.m4] ---'

Additionally, if you use Automake, the following additional productions come into play:

[acinclude.m4] --.
                 |
[local macros] --+--> aclocal* --> aclocal.m4
                 |
configure.ac ----'


configure.ac --.
               +--> automake* --> Makefile.in
Makefile.am ---'

Files used in configuring a software package:

                       .-------------> [config.cache]
configure* ------------+-------------> config.log
                       |
[config.h.in] -.       v            .-> [config.h] -.
               +--> config.status* -+               +--> make*
Makefile.in ---'                    `-> Makefile ---'

autoconf creates configure script, which produces

  • Makefile (s), ususally one in each subdirectory of package
  • (optionally) a C header file, containing #define directives
  • config.status script: which recreates files above
  • config.log for debugging

§§ GNU’s build (fuck-you) system

  • autoconf : produces configure script
  • automake
  • libtool : handles requirements for building shared libraries
  • gnulib : grabbing files fro mgnulib into own source tree.

§ libtool

§ License (same as GNU’s):


This manual (4 December 2023) is for GNU Autoconf (version 2.72), a package for
creating scripts to configure source code packages using templates and an M4
macro package.

Copyright © 1992–1996, 1998–2017, 2020–2023 Free Software Foundation, Inc.

    Permission is granted to copy, distribute and/or modify this document under
    the terms of the GNU Free Documentation License, Version 1.3 or any later
    version published by the Free Software Foundation; with no Invariant
    Sections, no Front-Cover texts, and no Back-Cover Texts. A copy of the
    license is included in the section entitled “GNU Free Documentation License.” 
🔲 ☆

Makefile

DISCLAIMER:

This is a collection of notes from various sources. I am not the author of any of the following content.

reference

THIS THIS AND THIS

§§ BASIC

A simple Makefile

1
2
test:
    echo "this is a test"

exec make test gets:

echo "this is a test"
this is a test

A general rule:

1
2
target: prerequisites
<TAB> recipe

§§ PHONY

Eli_Bendersky@StackOverflow https://stackoverflow.com/questions/2145590/what-is-the-purpose-of-phony-in-a-makefile

By default, Makefile targets are “file targets” - they are used to build files from other files. Make assumes its target is a file, and this makes writing Makefiles relatively easy:

1
2
foo: bar
  create_one_from_the_other foo bar

However, sometimes you want your Makefile to run commands that do not represent physical files in the file system. Good examples for this are the common targets “clean” and “all”. Chances are this isn’t the case, but you may potentially have a file named clean in your main directory. In such a case Make will be confused because by default the clean target would be associated with this file and Make will only run it when the file doesn’t appear to be up-to-date with regards to its dependencies.

These special targets are called phony and you can explicitly tell Make they’re not associated with files, e.g.:

1
2
3
.PHONY: clean
clean:
  rm -rf *.o

Now make clean will run as expected even if you do have a file named clean.

In terms of Make, a phony target is simply a target that is always out-of-date, so whenever you ask make <phony_target>, it will run, independent from the state of the file system. Some common make targets that are often phony are: all, install, clean, distclean, TAGS, info, check.

§§ clean

It is a good practice not to call clean in all or put it as the first target. clean should be called manually when cleaning is needed as a first argument to make:

$ make clean
Cleaning up...

§§ Variables and basic gcc compiling

1
2
3
4
5
CC = gcc
# This is also called a recursive expanded variable, and it is used in a rule as shown below:

hello: hello.c
    ${CC} hello.c -o hello

use make hello :

gcc hello.c -o hello

Avoiding infinite loop (self-reference)

an example of self-reference:

1
2
3
4
5
CC = gcc
CC = ${CC}

all:
    @echo ${CC}

which results in:

Makefile:8: *** Recursive variable 'CC' references itself (eventually).  Stop.

to avoid self-reference, use operator := (simply expanded variable):

1
2
3
4
5
CC := gcc
CC := ${CC}

all:
    @echo ${CC}

§§ Patterns and functions

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# Usage:
# make        # compile all binary
# make clean  # remove ALL binaries and objects

.PHONY = all clean

CC = gcc                        # compiler to use

LINKERFLAG = -lm

SRCS := $(wildcard *.c)
BINS := $(SRCS:%.c=%)

all: ${BINS}

%: %.o
        @echo "Checking.."
        ${CC} ${LINKERFLAG} $< -o $@

%.o: %.c
        @echo "Creating object.."
        ${CC} -c $<

clean:
        @echo "Cleaning up..."
        rm -rvf *.o ${BINS}

NOTES

  • .PHONY explicitly tells make which targets are not real files.
  • LINKERFLAG are used by gcc during compiling. In this case -lm means link math library.
  • wildcard *.c lists out all .c files
  • BINS := $(SRCS:%.c=%) ,This is called as substitution reference. In this case, if SRCS has values 'foo.c bar.c', BINS will have 'foo bar'.
  • all: ${BINS}: The phony target all calls values in ${BINS} as individual targets.
1
2
3
%: %.o
  @echo "Checking.."
  ${CC} ${LINKERFLAG} $< -o $@

Suppose foo is one of the values in ${BINS}. Then % will match foo, ( % can match any target name). Below is the rule in its expanded form:

1
2
3
foo: foo.o
  @echo "Checking.."
  gcc -lm foo.o -o foo

finally

1
2
3
%.o: %.c
  @echo "Creating object.."
  ${CC} -c $<

Every prerequisite in the previous rule is considered a target for this rule. Below is the rule in its expanded form:

1
2
3
foo.o: foo.c
  @echo "Creating object.."
  gcc -c foo.c
  • $< match the given prerequisite and $@ match the target name
🔲 ☆

archlinux setup + LUKS + LVM

system setup:

LUKS + LVM + (ext4) + archlinux. This is for experienced arch user. For detailed guide on arch installation please use archwiki

and

https://shrik3.com/post/archlinux/arch_setup_new/


                partition overview                         overview

NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS lsblk nvme0n1 259:0 0 953.9G 0 disk ├─nvme0n1p1 259:1 0 1G 0 part /boot └─nvme0n1p2 259:2 0 900G 0 part └─cryptlvm 253:0 0 900G 0 crypt ├─lvmroot-root 253:1 0 250G 0 lvm / ├─lvmroot-home 253:2 0 600G 0 lvm /home └─lvmroot-swap 253:3 0 48G 0 lvm [SWAP]

FS dev mappers mappers

/dev/mapper/lvmroot-root -> / /dev/mapper/lvmroot-home -> /home /dev/mapper/lvmroot-swap -> swapon

                luks PART I - init                        luks init

create the luks partition create

$ cryptsetup -v -y \ # verbose, ask password -c aes-xts-plain64 \ # cypher, default for LUKS2 -s 512 -h sha512 \ # key size, hash algo -i 2000 \ # 2 seconds to process pw –use-random \ # RNG –label=SOME_LABEL \ # .. luksFormat –type luks2 \ # format w/ luks2 /dev/nvme0n1p2 # the device

dump information of the luks partition luks info

$ cryptsetup luksDump /dev/nvme0n1p2

backup the luks headers (and save it to safe place) luks backup

$ cryptsetup luksHeaderBackup –header-backup-file
/a/path/header.img /dev/nvme0n1p2

manually open the luks device: luks open dev

$ cryptsetup open [–type luks2] /dev/nvme0n1p2 cryptlvm

                lvm setup                                 lvm setup

(first open the luks partition via cryptsetup open!)

create lvm physical volume and volume group open crypt dev

pvcreate/dev/mapper/cryptlvm pvcreate /dev/mapper/cryptlvm vgcreate lvmroot /dev/mapper/cryptlvm

create virtual partitions lvm partations

lvcreateL250Glvmrootroot lvcreate -L250G lvmroot root lvcreate -L650G lvmroot home $ lvcreate -L48G lvmroot swap

                file system                                      fs

mkfs.vfat -F32 /dev/nvme0n1p1 # the unencrypted part! mkfs.ext4 /dev/mapper/lvmroot-root # root mkfs.ext4 /dev/mapper/lvmroot-home # home mkswap /dev/mapper/lvmroot-swap # swap

mount the disks (see the overview above)

mount/dev/mapper/lvmrootroot/mnt mount /dev/mapper/lvmroot-root /mnt mkdir /mnt/boot /mnt/home mount/dev/mapper/lvmroothome/mnt/home mount /dev/mapper/lvmroot-home /mnt/home mount /dev/nvme0n1p1 /mnt/boot

                system setup (as always)                  sys setup

  • install the base system $ pacstrap -K /mnt base linux ….

  • generate $ genfstab -U /mnt » /nnt/etc/fstab

  • chroot into /mnt $ arch-chroot /mnt

  • set timezone, locale etc. $ skip

  • config hostname, users etc.

                  bootloader                                bootloader
    

mkinitcpio config mkinitcpio

/etc/mkinitcpio.conf HOOKS = … add [encrypt, lvm2] before [filesystems]

regenerate init image

$ mkinitcpio -P

grub config (install grub and efibootmgr first) grub

install grub

$ grub-install –target=x86_64-efi
–efi-directory=/boot
–bootloader-id=meow
–recheck

edit config: /etc/default/grub

§ add to GRUB_CMDLINE_LINUX:

cryptdevice=UUID=:cryptlvm root=/dev/lvmroot/root

generate grub config

$ grub-mkconfig -o /boot/grub/grub.cfg

                references

https://jadarma.github.io/blog/posts/2024/08/installing-nixos-with-flakes-and-lvm-on-luks/ https://gist.github.com/mjnaderi/28264ce68f87f52f2cabb823a503e673

vi: ts=2 vi: tw=72 vi: ft=text

🔲 ☆

nix 01 - Nix subsystem for arch

[BACK TO INDEX]

With massive copy-paste from the Nix Pills. This post is under the same CC-BY-SA-4.0 . (Co-)Authors list.

This post is intended to be a quick reference for arch-to-nix beginner (me).

§ Nix Subsystem for Arch

I’m learning and playing with nix to decide if I should hop to NixOS for my new work laptop.

arch install

# insteall `nix` for archlinux (native)
pacman -S nix
systemctl enable --now nix-daemon.service

env. variables

export PATH=$HOME/.nix-profile/bin:$PATH
# I prefer the nixos channel instead of the unstable.
# otherwise it could be:
# export NIX_PATH=`nixpkgs=channel:unstable`
export NIX_PATH=`nixpkgs=channel:nixos`

install nix (again?) well, because from this point I’ll use nix as a self-contained unit independent of the arch system package. Also this won’t work if you use the unstable channel

nix-channel add  https://nixos.org/channels/nixos-25.05
nix-channel --update
nix-env -iA nix

environment: The user environment is defined by manifest.nix.. I don’t think it’s meant to be human readable.. Uninstalling from the environment doesn’t remove the package itself. (If I understand correctly it simply creates a new generation that has no package).

$ nix-env -e '*'    # danger, this removes everything from the env

to undo this, manually locate the nix-env binary and rollback.

/nix/store/q7v3i9ii8mp6pjasxwip4ybq79hzxj1q-nix-2.28.4/bin/nix-env --rollback

channels

frequently used commands

nix-env -iA <pkg>           # install pkg for (all) users

# Queries
nix-env --list-generations
nix-env -q                  # query installed packages
nix-env -q --out-path       # also shows their _actual_ locations
nix-env --rollback          # rollback to the previous generation

# The argument points to something in the nix-store
nix-store -q --references $(which hello)  # runtime dependencies of hello
nix-store -qR [...]                       # the closure, recursive deps
nix-store -q --tree [...]                 # closure in tree display
nix-store -q --referrers  $(which hello)  # the reverse dependencies of hello

Caveats

  • they recommand you to use the unstable channel but this can be very broken. For example the manpages are missing.
  • Never ever try to manually modify /nix/store/*
🔲 ☆

Memory Jargons

/proc/meminfo (free)

$ man proc_meminfo
MemTotal (total)
total usable RAM i.e. total physical RAM minus reserved bits and kernel binary code.
MemAvailable
memory that can bed used if there is demand. Memory could be used for file caches by the kernel and still marked as availabe.
MemFree (free)
the “free” memory per se. Memory that is not used for ANY purpose. This is roughly MemAvailable - Cache - Buffer.
Low/HighFree
amount of free Low/High memory (see notes below)
Low/HighTotal
total amount of Low/High memory

Cached In-memory cache for files read from disk (excl. SwapCached)

Buffers TODO

SwapTotal/Free Amount of total/free swap space

SwapCached Memory that once was swapped out, is swapped back in but still also is in the swap file. (If memory pressure is high, these pages don’t need to be swapped out again because they are already in the swap file. This saves I/O.)

Active / Inactive; also for anon and file Memory recently (/ less) used; ususally not (/ more eligible) to reclaim.

Unevictable

MLocked

  • used: memory in use
  • free: memory not in use
  • shared
  • buffers
  • cached
  • shared / buffers / cached values are included in used

Low and High memory

dogma: with paging enabled, the OS can only access memory via virtual address.

This is rather a legacy term. 32bit kernel can address 2^32 = 4GiB of virtual memory. A typical config is that kernel takes upper 1GiB and user takes lower 3GiB. The kernel can map ~860 MB of physical memory; Physical memory above this line is highmem. Access to highmem requires temporary mapping and is slower.

In contrast, 64bits kernel has a virtual memory space (48 bits = 256 TB) much larger than physical memory, the kernel can map the whole available physical address space to its virtual address space via a fixed mapping e.g.

    VA = PA + offset

/proc/status


$ free -h

      total   used   free  shared  buff/cache  available
Mem:   15Gi  9.7Gi  2.1Gi   2.9Gi       6.8Gi      5.7Gi
Swap:  15Gi  725Mi   15Gi

$ cat /proc/<pid>/ status # only showing memory related

Name:       systemd
VmPeak:    31296 kB
VmSize:    23560 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:     20864 kB
VmRSS:     14244 kB
RssAnon:    4948 kB
RssFile:    9296 kB
RssShmem       0 kB
VmData:     4464 kB
VmStk:       132 kB
VmExe:        56 kB
VmLib:     12112 kB
VmPTE:        92 kB
VmSwap:      424 kB
HugetlbPages:  0 kB
Mems_allowed:   [SNIP]
Mems_allowed_list:  0
🔲 ☆

RDMA 101 - basics

SRC: Netdev 0x16: RDMA Tutorial by Roland Dreier (Enfabrica) and Jason Gunthorpe (NVIDIA)
https://netdevconf.info/0x16/slides/40/RDMA%20Tutorial.pdf

Introduction to Programming Infiniband RDMA by Insu Jang
https://insujang.github.io/2020-02-09/introduction-to-programming-infiniband/

Code

Copy-Verbatim, all rights belong to the original author(s)

Async queues:

  • work requests are sent to send/recv queues
  • poll completion queue for completion
One-sided operations (RDMA)
one host moves data directly to or from memory of its communication peer without notifying its CPU
Two-sided operations
(1) one host posts a receive work request (2) peer posts a send work requests that consumes the recv work request to deliver data

one-/or two-sided operations can be mixed.

transport layers

Transport Layering

            [Application]
             _____|_____ 
            |           |
      [UD QPs]        [RC QPs]
            |           |
            +-----+-----+
                  |      
            [   Verbs   ]                       libverbs
                  |
  ________________|_________________
  |        |          |             |
[RoCE]  [iWARP]  [InfiniBand]  [Omni-Path]      Transport
  |________|
      |
  [Ethernet]        [IB]       [Omni-Path]      Physical

SW

  • librdmacm connection establishment w/ IP addressing
  • libverbs API for control/data path operations. “verbs” interface implementation

Lingua

Reliable Connected (RC)

Unreliable Diagram (UD)

Queue Pair (QP), Completion Queue (CQ), Send Queue (SQ), Receive Queue (RQ)
SQ and RQ are always grouped and managed as a queue pair (QP). SQ and RQ in a queue pair could use distinct CQ or share one.
   CA 1                 CA 2
   ----                 ----
   SEND --------------> RECV
   RECV <-------------- SEND
Work Request (WR), Work Completion (WC)
post WR by generating a work queue entry (WRE) into the work queue. e.g. SEND WR to SQ; RECV WR to RQ. Once a request is completed, the HW posts a Work Completion (WC) into a CQ.

Protection Domain (PD)

Memory Region (MR)

InfiniBand (IB)

Channel Adapter (CA)
an end node in the IB network (comparable to a NIC)

Host Channel Adapter (HCA)

🔲 ☆

statistic tools - 去海边整点统计工具

§ Mann-Kendall test for monotonic trend

https://vsp.pnnl.gov/help/vsample/design_trend_mann_kendall.htm

§ Petri Nets

Petri Nets fundamentals

Stochastic Petri Nets

§ odds ratio and relative risk

Settings:

  • There are 2000 students in the campus. (composition shown in table)
  • In practice we cannot study all of the 2000 students. And we must do sampling.

Ground truth

exercise (E) no exercise (Ne) Sum
Pass Exam (P) 500 700 1200
Fail Exam (F) 46 754 800
Sum 546 1454 2000



Thesis: not going to exercise increases risk of failing the exam.

A lecturer wants to study the Relative Risk of failing exam for student to do not go to exams.

RR=FNePNe+FNe:FEPE+FE \begin{aligned} RR &= \frac{F_{Ne}}{P_{Ne} + F_{Ne}} : \frac{F_{E}}{P_{E} + F_{E}}\\\\ \end{aligned}
❌