NOPFunction rename, added ualarm link, added rule of thumb for interval
This commit is contained in:
parent
54d3b00d54
commit
e214322fc3
19
README.md
19
README.md
@ -71,10 +71,10 @@ Muster: `./src/cache_test.c`
|
|||||||
|
|
||||||
**Jetzt können wir den Cache doch mal als Medium verwenden. Der Sender kann `0` und `1` über den (ausbleibenden) Speicherzugriff kodieren. Der Empfänger interpretiert dann, je nach Zugriffszeit.**
|
**Jetzt können wir den Cache doch mal als Medium verwenden. Der Sender kann `0` und `1` über den (ausbleibenden) Speicherzugriff kodieren. Der Empfänger interpretiert dann, je nach Zugriffszeit.**
|
||||||
|
|
||||||
`sharedlib.c` sieht so aus:
|
Um zu kommunizieren, müssen sich Sender und Empfänger auf eine physische Adresse einigen, die für Flush+Reload verwendet wird. Dafür nehmen wir am besten eine shared library, die ist schon als `sharedlib.c` bereitgestellt:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
void function(void)
|
void myStupidNOPFunction(void)
|
||||||
{ asm volatile (
|
{ asm volatile (
|
||||||
"nop\n\t"
|
"nop\n\t"
|
||||||
"nop\n\t"
|
"nop\n\t"
|
||||||
@ -90,11 +90,13 @@ void function(void)
|
|||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
Die Adresse von `function` kann also zum Flushen und Reloaded verwendet werden.
|
Die Adresse von `myStupidNOPFunction` kann also zum Flushen und Reloaded verwendet werden.
|
||||||
Da immer eine gesamte Cacheline geladen wird, sollte sich nichts anderes in dem selben 64Byte Block befinden.
|
Da immer eine gesamte Cacheline geladen wird, sollte sich nichts anderes in dem selben 64Byte Block befinden.
|
||||||
Die Funktionen `padding_before` und `padding_after` sind beide 64 Byte groß, also eine Cacheline.
|
Die Funktionen `padding_before` und `padding_after` sind beide 64 Byte groß, also eine Cacheline.
|
||||||
Damit kann dann auch gar nichts mehr schief gehen :)
|
Damit kann dann auch gar nichts mehr schief gehen :)
|
||||||
|
|
||||||
|
*`MyStupidNOPFunction` ist übrigens genau $256*64\ Byte$ groß. Das wird vielleicht ja noch praktisch ;)*
|
||||||
|
|
||||||
`sharedlib.c` kann man so kompilieren und linken:
|
`sharedlib.c` kann man so kompilieren und linken:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -107,13 +109,13 @@ gcc -O0 empfaenger.c lib.c -L. -lsharedlib -o empfaenger
|
|||||||
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
|
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
|
||||||
```
|
```
|
||||||
|
|
||||||
*(oder einfach `cmake` verwenden)*
|
*(oder einfach `cmake` verwenden :P)*
|
||||||
|
|
||||||
dann kann man `function` verwenden:
|
dann kann man `function` benutzen:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
# in e.g. sender.c
|
# in e.g. sender.c
|
||||||
maccess((void *) function)
|
maccess((void *) myStupidNOPFunction)
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
##### Tips
|
##### Tips
|
||||||
@ -121,13 +123,13 @@ maccess((void *) function)
|
|||||||
- `taskset` zum kann pinnen der Programme auf einen bestimmten CPU-Kern benutzt werden. Das kann helfen.
|
- `taskset` zum kann pinnen der Programme auf einen bestimmten CPU-Kern benutzt werden. Das kann helfen.
|
||||||
- Verwendet man blockierenden Sleep um zu Takten, z.B. `clock_nanosleep`, dann sollte man unbedingt darauf achten nicht eine Periodendauer zu schlafen, sondern nur bis zum nächsten Zeitabschnitt. Einfacher geht es mit nicht-blockierendem Sleep, z.B. `ualarm`.
|
- Verwendet man blockierenden Sleep um zu Takten, z.B. `clock_nanosleep`, dann sollte man unbedingt darauf achten nicht eine Periodendauer zu schlafen, sondern nur bis zum nächsten Zeitabschnitt. Einfacher geht es mit nicht-blockierendem Sleep, z.B. `ualarm`.
|
||||||
|
|
||||||
So kann man `ualarm` nutzen, um alle x µs einen `SIGARLM` auszulösen:
|
So kann man `ualarm` [Linux Manual](https://man7.org/linux/man-pages/man3/ualarm.3.html) nutzen, um alle x µs einen `SIGARLM` auszulösen:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
int main(void){
|
int main(void){
|
||||||
...
|
...
|
||||||
signal(SIGALRM, signal_handler);
|
signal(SIGALRM, signal_handler);
|
||||||
ualarm(sample_interval, sample_interval);
|
ualarm(0, interval);
|
||||||
```
|
```
|
||||||
|
|
||||||
Bei jedem `SIGALRM` Signal wird `signal_handler` ausgeführt:
|
Bei jedem `SIGALRM` Signal wird `signal_handler` ausgeführt:
|
||||||
@ -142,6 +144,7 @@ void signal_handler(int signo) {
|
|||||||
|
|
||||||
- Der Zeitabstand von Flush zu Reload sollte MAXIMIERT werden! Dies ist das Zeitfenster, in welchem der Sender die Adresse(n) zurück in den Cache laden kann.
|
- Der Zeitabstand von Flush zu Reload sollte MAXIMIERT werden! Dies ist das Zeitfenster, in welchem der Sender die Adresse(n) zurück in den Cache laden kann.
|
||||||
- Der Sender kann nicht nur einmal Laden. Das kann man auch mehrfach in einem Zeitfenster machen, um sicher zu gehen, dass die Cacheline auch geladen ist, wenn der Empfänger ausließt.
|
- Der Sender kann nicht nur einmal Laden. Das kann man auch mehrfach in einem Zeitfenster machen, um sicher zu gehen, dass die Cacheline auch geladen ist, wenn der Empfänger ausließt.
|
||||||
|
- **Richtwert**: 1000µs pro Zyklus haben sich als ganz gut erwiesen (→ 1kHz). Ein zu kurzes Zeitfenster lässt nicht genug Zeit um alle Instruktionen abzuarbeiten, ein zu langes führt zu mehr Noise, falls die Cacheline zwischenzeitlich aus dem Cache verdrängt wird.
|
||||||
|
|
||||||
### Block 3: Einen String über den Cache als Medium senden
|
### Block 3: Einen String über den Cache als Medium senden
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user