Ich denke, die einfachste Lösung wäre, ein Zeichengerät in Ihrem Kerneltreiber mit eigenen Dateioperationen für eine virtuelle Datei zu erstellen. Dann kann der Userspace dieses Gerät O_RDWR
öffnen . Sie müssen zwei Hauptdateioperationen implementieren:
-
read
-- so übergibt der Kernel Daten zurück an den Userspace. Diese Funktion wird im Kontext des Userspace-Threads ausgeführt, derread()
aufruft Systemaufruf, und in Ihrem Fall sollte es blockieren, bis der Kernel einen anderen Seed-Wert hat, für den er die Ausgabe kennen muss. -
write
-- so übergibt der Userspace Daten an den Kernel. In Ihrem Fall würde der Kernel einfach die Antwort auf den vorherigen Lesevorgang nehmen und an die Hardware weitergeben.
Dann endet man mit einer einfachen Schleife im Userspace:
while (1) {
read(fd, buf, sizeof buf);
calculate_output(buf, output);
write(fd, output, sizeof output);
}
und überhaupt keine Schleife im Kernel - alles läuft im Kontext des Userspace-Prozesses, der die Dinge antreibt, und der Kernel-Treiber ist nur dafür verantwortlich, die Daten zur/von der Hardware zu verschieben.
Je nachdem, was Ihr "do some random stuff here" auf der Kernel-Seite ist, ist es möglicherweise nicht möglich, dies ganz so einfach zu tun. Wenn Sie die Kernel-Schleife wirklich brauchen, müssen Sie einen Kernel-Thread erstellen, um diese Schleife auszuführen, und dann einige Variablen nach dem Vorbild von input_data
haben , input_ready
, output_data
und output_ready
, zusammen mit ein paar Warteschlangen und was auch immer Sie brauchen.
Wenn der Kernel-Thread Daten liest, fügen Sie die Daten in input_ready
ein und stellen Sie den input_ready
ein kennzeichnen und signalisieren Sie die Eingangswarteschlange und führen Sie dann wait_event(<output_ready is set>)
aus . Die read
Dateioperation würde einen wait_event(<input_ready is set>)
ausführen und die Daten an den Userspace zurückgeben, wenn sie fertig sind. Ebenso der write
Dateioperation würde die Daten, die sie aus dem Userspace bekommt, in output_data
schreiben und setzen Sie output_ready
und signalisieren der Ausgabewarteschlange.
Ein anderer (hässlicher, weniger portierbarer) Weg ist etwas wie ioperm
zu verwenden , iopl
oder /dev/port
alles vollständig im Userspace zu erledigen, einschließlich des Low-Level-Hardwarezugriffs.