Forum: Compiler & IDEs Namenskonventionen C


von Bauform B. (bauformb)


Lesenswert?

Stefans Frage hat mich an etwas erinnert, was ich nie zu fragen wagte. 
In C gibt es ja globale Variablen, z.B. in Interrupt-Routinen. Mit einem 
RTOS braucht man etwas ähnliches, um Daten zwischen zwei Tasks 
auszutauschen. Solche Variablen sind ja "über-global" -- wie nennt man 
die? Galaktische oder interplanetare Variablen?

Ja, ein RTOS bietet Mechanismen mit denen die Frage nicht aufkommt. Aber 
wenn man auf einem uC den kleinen Dienstweg gehen will? Auch wenn man 
offizielles shared memory benutzt: da drin sind auch Variablen 
versteckt, die mehr als global sind.

:
von Cyblord -. (cyblord)


Lesenswert?

Mehr als global? Warum? Global ist global. Was rauchst du eigentlich?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bauform B. schrieb:
> Solche Variablen sind ja "über-global" -- wie nennt man die?

Die sind global (Sichtbarkeit) und statisch (Lebensdauer).

Wenn du innerhalb einer Übersetzungseinheit (also C-Quelle plus alle 
#includes) eine Variable auf dem äußeren Level ohne weitere 
Schlüsselworte anlegst, wird sie genau das: global. Legst du sie an der 
gleichen Stelle mit "static" an, bleibt die Lebensdauer statisch, aber 
die Sichtbarkeit wird auf die Übersetzungseinheit beschränkt. Code aus 
anderen Übersetzungseinheiten kann auf sie nicht zugreifen.

von JoF. (Gast)


Lesenswert?

Jörg W. schrieb:
> Die sind global (Sichtbarkeit) und statisch (Lebensdauer).
>
> Wenn du innerhalb einer Übersetzungseinheit (also C-Quelle plus alle
> #includes) eine Variable auf dem äußeren Level ohne weitere
> Schlüsselworte anlegst, wird sie genau das: global. Legst du sie an der
> gleichen Stelle mit "static" an, bleibt die Lebensdauer statisch, aber
> die Sichtbarkeit wird auf die Übersetzungseinheit beschränkt. Code aus
> anderen Übersetzungseinheiten kann auf sie nicht zugreifen.

Genauso habe ich es mal gelernt 👍

von A. S. (Gast)


Lesenswert?

Bauform B. schrieb:
> . Mit einem RTOS braucht man etwas ähnliches, um Daten zwischen zwei
> Tasks auszutauschen. Solche Variablen sind ja "über-global" -- wie nennt
> man die? Galaktische oder interplanetare Variablen?

Sie sind "volatile".

Und dazu unter Umständen auch nicht atomar, brauchen als einen 
synchronisationsmechanismus.

Bei manchen Prozessoren sind alle integer-Typen atomar, bei anderen 
können 16 Bit schon Müll ergeben.

Dazu braucht es kein RTOS, Interrupts bewirken das gleiche.

von Bauform B. (bauformb)


Lesenswert?

Jörg W. schrieb:
> Wenn du innerhalb einer Übersetzungseinheit (also C-Quelle plus alle
> #includes) eine Variable auf dem äußeren Level ohne weitere
> Schlüsselworte anlegst, wird sie genau das: global.

Einverstanden. Und alle Übersetzungseinheiten, die damit gelinkt werden, 
sehen sie auch. Aber auch nur die. Für alles, was getrennt gelinkt wird 
(anderer Prozess, Task, Programm...), wird sie erst sichtbar, wenn man 
ein attribute wie ((section ("shared_memory"))) dazu schreibt.

Ich meine, das ist unterschiedlich genug zum normalen global, das 
verdient einen eigenen Namen. Ich rede nur von kleinen uC, gerade groß 
genug  für etwas RTOS-ähnliches.


Cyblord -. schrieb:
> Was rauchst du eigentlich?

Lack von überlasteten Widerständen. Aber dank SMD nicht mehr so viel wie 
früher. Außerdem: heute dampft man ja, vor allem Flussmittel.

von Bauform B. (bauformb)


Lesenswert?

A. S. schrieb:
> Bauform B. schrieb:
>> . Mit einem RTOS braucht man etwas ähnliches, um Daten zwischen zwei
>> Tasks auszutauschen. Solche Variablen sind ja "über-global" -- wie nennt
>> man die? Galaktische oder interplanetare Variablen?
>
> Sie sind "volatile".
>
> Und dazu unter Umständen auch nicht atomar, brauchen als einen
> synchronisationsmechanismus.

Auch einverstanden.

> Dazu braucht es kein RTOS, Interrupts bewirken das gleiche.

Ja, was volatile und atomar betrifft. Wenn man aber mehrere "Programme" 
getrennt linkt, die aber zusammen arbeiten müssen (z.B. Steuerung und 
Benutzerschnittstelle), braucht man einen zusätzlichen Mechanismus.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bauform B. schrieb:
> Für alles, was getrennt gelinkt wird (anderer Prozess, Task,
> Programm...), wird sie erst sichtbar, wenn man ein attribute wie
> ((section ("shared_memory"))) dazu schreibt.

Nö. Woher sollten die irgendwelche Namen völlig separat gelinkter 
Programme erfahren?

Wenn es irgendwo einen shared memory zwischen verschiedenen Programmen 
gibt, kann es nur auf Absprachen beruhen, wie dieser aufgebaut ist. 
Solche Absprachen kann man natürlich automatisch aus den 
Symboltabellen generieren, aber das ist dann nichts mehr, was irgendwo 
allgemein definiert wäre. Die Sprache C kennt erstmal nichts, was ein 
"shared memory" sein soll.

Ein bisschen anders ist es noch, wenn zur Laufzeit dynamische 
Bibliotheken nachgeladen werden (dlsym und Konsorten): diese haben eine 
Symboltabelle, über die man wieder zu den Namen Werte bekommen kann. 
Diese verhalten sich ab dem Moment aber wieder wie alle anderen globalen 
Variablen; die so geladene Bibliothek wird ja (temporärer) Bestandteil 
des Programms.

von Bauform B. (bauformb)


Lesenswert?

Jörg W. schrieb:

> Woher sollten die irgendwelche Namen völlig separat gelinkter
> Programme erfahren?

Die Programme benutzen zwei includes gemeinsam: eins mit typedef struct 
und eins in ihrem Linkerscript für die absolute Adresse (letztlich die 
Adresse der struct).

von foobar (Gast)


Lesenswert?

> Mit einem RTOS braucht man etwas ähnliches, um Daten zwischen zwei
> Tasks auszutauschen. Solche Variablen sind ja "über-global" -- wie
> nennt man die? Galaktische oder interplanetare Variablen?

Im Kontext von Multithreading gibt es thread-local Variablen[1].  Vom 
Scope meist global (können aber z.B. auch static locals sein), aber 
jeder Thread hat eine private Kopie (bei Linux z.b. errno).  Die 
normalen Variablen sind thread-global - für alle Threads gemeinsam (dein 
"über-global").

Im Kontext von mehreren Prozessen mit getrennten Adressräumen bieten die 
Betriebssysteme unterschiedliche  Methoden der 
Inter-Process-Communication (IPC) - bei Unix u.a. shared memory via 
sysv-shm oder mmap(MAP_SHARED).  Auf der Sprachebene von C/C++ findet 
man da üblicherweise nichts.


[1] https://gcc.gnu.org/onlinedocs/gcc/Thread-Local.html

von A. S. (Gast)


Lesenswert?

Bauform B. schrieb:
> Die Programme benutzen zwei includes gemeinsam: eins mit typedef struct
> und eins in ihrem Linkerscript für die absolute Adresse (letztlich die
> Adresse der struct).

Es gibt Mechanismen, um Variablen an feste Orte zu legen.

Manuell (wie z.b. Registern), dynamisch (das eine Programm sucht im 
anderen, zur Link- oder Laufzeit), per Interface (Pointer-austausch), 
per Linkeranweisung, etc. etc.

Am Ende spielt das aber keine Rolle. Es bleiben vom Prinzip her globale 
Variablen.

Oder auf was möchtest Du hinaus. Bzw. wie sprichst Du die an, was ist 
für Dich der Unterschied?

von Bauform B. (bauformb)


Lesenswert?

A. S. schrieb:
> Oder auf was möchtest Du hinaus.

Im Grunde geht es mir um die unterschiedliche Sichtbarkeit.
 1. nur für eine Funktion
 2. für alle Funktionen in einer Quell-Datei
 3. überall im ganzen Programm
 4. für alle Programme auf dem gleichen uC
 5. für alle Programme auf allen CPUs im ganzen Rack (naja...)
1. bis 3. kennt jeder, das ist normales C in einem einzelnen Programm. 
Mit Multitasking kommt die 4 dazu. Die ist identisch mit 3, solange man 
alles zusammen linkt. Ich fand es angenehmer, die "Programme" auch 
getrennt zu linken. Damit brauche ich einen neuen Mechanismus, weil 
normale globale Variablen nicht mehr funktionieren. Und ich dachte, 
dafür muss es doch einen Namen geben, so als Fortsetzung von 1=lokal 
über 3=global müsste 4 interplanetar heißen oder so.

> Bzw. wie sprichst Du die an, was ist für Dich der Unterschied?

Zur Zeit sind alle gemeinsamen Daten in einer struct in einer extra 
section verpackt. Die wird per Linkerscript auf eine feste Adresse 
gelegt. Per "extern" kann das jeder ziemlich normal benutzen.

Gerade fällt mir ein: Stattdessen könnte sich eine Funktion auch einen 
Pointer vom "Betriebssystem" holen. Dann sind die gemeinsamen Daten nur 
für diese Funktion sichtbar. Das sieht garnicht mehr global aus, damit 
entfällt der Punkt 4 komplett und ich brauche keinen neuen Begriff -- 
sehr vorteilhaft! Das wäre zwar langsamer als die jetzige rein statische 
Lösung, aber immer noch besser als ausgewachsene IPC.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bauform B. schrieb:

> Im Grunde geht es mir um die unterschiedliche Sichtbarkeit.
>  1. nur für eine Funktion
>  2. für alle Funktionen in einer Quell-Datei

Gibt's in C nicht. Das Konstrukt heißt dort "Übersetzungseinheit" 
(translation unit), und das umfasst halt auch alle inkludierten Dateien.

>  3. überall im ganzen Programm

Bis hierhin definiert der C-Standard sowas.

>  4. für alle Programme auf dem gleichen uC

Da verlässt du den C-Standard.

Aber auch APIs, die sowas wie shared memory kennen (mmap() in Posix oder 
das SystemV shmem interface) haben da keinerlei Vorkehrungen außer dem 
puren Teilen eines gemeinsamen Speicherbereichs. Was in diesem 
Speicher steht ist, schrieb ich oben, gegenseitige Absprache. Man tut 
natürlich im allgemeinen gut daran, wenn sich alle beteiligten Seiten in 
dieser Absprache untereinander einig sind. :-))

>  5. für alle Programme auf allen CPUs im ganzen Rack (naja...)

In der Regel gar nicht. Soweit ich weiß, benutzen diese völlig separate 
Speicher, die nicht verbunden sind. Hatte ich aber noch nicht in der 
Hand.

von A. S. (Gast)


Lesenswert?

Bauform B. schrieb:
> Im Grunde geht es mir um die unterschiedliche Sichtbarkeit.
>  1. nur für eine Funktion
da fehlt noch 0, innerer Block Scrope
>  2. für alle Funktionen in einer Quell-Datei
>  3. überall im ganzen Programm
>  4. für alle Programme auf dem gleichen uC
Z.B. Register, Memory-Mapped IO, … also ganz normal global.
>  5. für alle Programme auf allen CPUs im ganzen Rack (naja...)
Da Verlässt Du C und kommst zu sowas, was bei uns in der Firma 
"Parameter" heisst. Mit physicher Kommunikation zwischen den CPUs. Also 
weit weg von "Variablen" im herkömmlichen Sinn.
> 1. bis 3. kennt jeder, das ist normales C in einem einzelnen Programm.
> Mit Multitasking kommt die 4 dazu.
OK. Ich assoziiere Multitasking auf µC mit EINEM gelinkten Programm, wie 
z.B. bei FreeRTOS, µITRON, sowas halt und 1 bis 100 Tasks. Was Du meinst 
ist  für mich eher ein OS wie DOS oder OSx.

> Gerade fällt mir ein: Stattdessen könnte sich eine Funktion auch einen
> Pointer vom "Betriebssystem" holen. Dann sind die gemeinsamen Daten nur
> für diese Funktion sichtbar. Das sieht garnicht mehr global aus, damit
> entfällt der Punkt 4 komplett und ich brauche keinen neuen Begriff --
O.T.: Ich habe noch nie verstanden, warum "versteckte" Variablen, auf 
die ich jederzeit beliebig viele Pointer bekommen kann, nicht global 
sein sollen.

Beitrag #6490806 wurde von einem Moderator gelöscht.
Beitrag #6490808 wurde von einem Moderator gelöscht.
Beitrag #6490811 wurde von einem Moderator gelöscht.
von Rolf M. (rmagnus)


Lesenswert?

Bauform B. schrieb:
> Einverstanden. Und alle Übersetzungseinheiten, die damit gelinkt werden,
> sehen sie auch. Aber auch nur die. Für alles, was getrennt gelinkt wird
> (anderer Prozess, Task, Programm...), wird sie erst sichtbar, wenn man
> ein attribute wie ((section ("shared_memory"))) dazu schreibt.
>
> Ich meine, das ist unterschiedlich genug zum normalen global, das
> verdient einen eigenen Namen. Ich rede nur von kleinen uC, gerade groß
> genug  für etwas RTOS-ähnliches.

Dort hat man dann aber auch keine separaten Prozesse mit eigenen 
Adressräumen.

>>  5. für alle Programme auf allen CPUs im ganzen Rack (naja...)
> Da Verlässt Du C und kommst zu sowas, was bei uns in der Firma
> "Parameter" heisst. Mit physicher Kommunikation zwischen den CPUs. Also
> weit weg von "Variablen" im herkömmlichen Sinn.

Es gibt auch noch reflective shared memory. Da greifen die Programme 
auch über Rechnergrenzen auf einen Shared-Memory zu, der von der 
Hardware im Hintergrund über einen schnellen Link synchron gehalten 
wird. Das funktioniert dann sogar, wenn unterschiedliche Betriebssysteme 
auf den Rechnern laufen.

>> 1. bis 3. kennt jeder, das ist normales C in einem einzelnen Programm.
>> Mit Multitasking kommt die 4 dazu.
> OK. Ich assoziiere Multitasking auf µC mit EINEM gelinkten Programm, wie
> z.B. bei FreeRTOS, µITRON, sowas halt und 1 bis 100 Tasks. Was Du meinst
> ist  für mich eher ein OS wie DOS oder OSx.

Klassisches DOS hat kein Multitasking.

> O.T.: Ich habe noch nie verstanden, warum "versteckte" Variablen, auf
> die ich jederzeit beliebig viele Pointer bekommen kann, nicht global
> sein sollen.

Weil sich "global" nicht auf den Zugriff auf die Daten, sondern auf die 
Sichtbarkeit des Namens bezieht.

von A. S. (Gast)


Lesenswert?

Rolf M. schrieb:
>> OK. Ich assoziiere Multitasking auf µC mit EINEM gelinkten Programm, wie
>> z.B. bei FreeRTOS, µITRON, sowas halt und 1 bis 100 Tasks. Was Du meinst
>> ist  für mich eher ein OS wie DOS oder OSx.
>
> Klassisches DOS hat kein Multitasking.
Richtig. Dem TO ging es aber darum, getrennt gelinkte Programme auf 
einem µC laufen zu lassen. Das ist etwas, was mit einem RTOS eher 
ungewöhnlich ist, bei DOS die Regel.

>> O.T.: Ich habe noch nie verstanden, warum "versteckte" Variablen, auf
>> die ich jederzeit beliebig viele Pointer bekommen kann, nicht global
>> sein sollen.
>
> Weil sich "global" nicht auf den Zugriff auf die Daten, sondern auf die
> Sichtbarkeit des Namens bezieht.
Naja, dass ist eine der sinnvollen Definitionen. Und das Zumüllen mit 
Namen ist ein Issue. Die allermeisten Empfehlungen, globale Variablen zu 
vermeiden, beziehen sich jedoch auf die Möglichkeit, von überall 
unkontrolliert drauf zugreifen zu können. Das ist bei dem Weg weiterhin 
der Fall. Und statt des namens der Variable braucht es den Namen des 
Pointers oder der Pointer-Get-Funktion. Oder man hat fest vereinbarte 
Adressen, was m.E. noch schlechter ist.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.