setsid() – neue Sitzung erstellen (linux)

Für allgemeine Fragen zur Programmierung, welche nicht! direkt mit Lazarus zu tun haben.
Antworten
Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

setsid() – neue Sitzung erstellen (linux)

Beitrag von Mathias »

Ich habe grade wieder was lustiges entdeckt.

Ich habe folgendes, mit ein wenig Änderung probiert hier probiert
https://www.ibm.com/docs/en/zos/2.4.0?t ... s-group-id

Da wird irgendwie ein neuer Prozess gestartet. Es kommt "Halt(0)", aber das Ganze läuft im else-Block weiter.
Nur wie kommt er in den else-Block ?
Er kann doch nicht gleichzeigt im then und else - Block sein ?
Wen er das Programm 2x starten würde, dann müsste nach meiner Meinung das "WriteLn('begin'); " 2x kommen :!:

Code: Alles auswählen

program project1;
uses
  ctypes;

  procedure setsid; cdecl; external 'c';
  function fork: cint; cdecl; external 'c';
  function getpgrp: cint; cdecl; external 'c';
  function sleep(sec: cint): cint; cdecl; external 'c';

  procedure main;
  var
    pid: cint = 0;
    i: integer;
  begin
    WriteLn('begin');
    if (pid = fork) = False then begin
      WriteLn('1. child''s process group id is ', getpgrp);
      setsid;
      WriteLn('2. child''s process group id is now ', getpgrp);
      Halt(0);
    end else begin
      WriteLn('3. child''s process group id is ', getpgrp);
      for i := 0 to 9 do begin
        sleep(1);
        WriteLn(i);
      end;
    end;
    WriteLn('end');
  end;

begin
  main;
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: setsid() – neue Sitzung erstellen (linux)

Beitrag von Socke »

Mathias hat geschrieben:
Di 11. Jul 2023, 16:17
Da wird irgendwie ein neuer Prozess gestartet. Es kommt "Halt(0)", aber das Ganze läuft im else-Block weiter.
  • Das Betriebssystem startet einen Prozess 1, in dem das von dir gestartetete Programm läuft. Prozess 1 schreibt "begin" auf die Konsole.
  • Beim Aufruf von fork wird dein Prozess 1 geklont, Prozess 2 starten im (fast) selben Zustand.
  • In Prozess 1 liefert fork die Prozess-ID 2 zurück, in Prozess 2 liefert fork die Prozess-ID 0 zurück (siehe Man-Page https://linux.die.net/man/2/fork)
  • Beide Prozesse haben eine eigene Variable pid mit dem gleichen Inhalt 0. Diesen vergleichen sie mit dem Rückgabewert von fork. Daher läuft Prozess 1 im then-Zweig weiter und Prozess 2 läuft im else-Zweig weiter.
Mathias hat geschrieben:
Di 11. Jul 2023, 16:17
Nur wie kommt er in den else-Block ?
Er kann doch nicht gleichzeigt im then und else - Block sein ?
Es sind zwei Prozesse, die unterschiedliche Pfade nehmen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1436
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: setsid() – neue Sitzung erstellen (linux)

Beitrag von fliegermichl »

Das ist ein toller Mechanismus.
Ich hab das mal für eine Serveranwendung genutzt.
Der Hauptprozess wartet auf eine eingehende Verbindung.
Sobald die hergestellt ist, stellt er mit fpfork eine Kopie her, die die aktuelle Verbindung abarbeitet und der Hauptprozess wartet wieder auf eine neue Verbindung.

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: setsid() – neue Sitzung erstellen (linux)

Beitrag von Mathias »

@Socke
Danke für die Antwort, jetzt verstehe ich langsam um was es geht. Ich habe schon gegoogelt, wurde aber nicht schlau.

@alle
Ich habe jetzt folgendes probiert, das sieht man gut, das da 2 Prozesse parallel laufen, beide in einer Endlosschlaufe gefangen.
Da sieht man besser, was passiert, als bei der Seite von IBM.

Code: Alles auswählen

  begin
    WriteLn('begin');
    if fork <> 0 then begin
      setsid;
      repeat
        Write('A');
      until False;;
    end else begin
      repeat
        Write('B');
      until False;;
    end;
Was bei dem Beispiel noch interessant ist, Write wird ohne Probleme ausgeführt.
Ich hatte mal mit Threading uns Semphores Versuche gemacht, das musste man recht aufpassen, das mit Write nicht das Programm abstürzt, weil sich die Prozesse in die Quere kommen.
Sobald die hergestellt ist, stellt er mit fpfork eine Kopie her
Anscheinend schon eingebaut bei der Unit "baseunix".
Aber setsid etwas merkwürdig, anstelle eine C-lib Anbindung, wird eine function aufgerufen.

Code: Alles auswählen

function fpsetsid : pid_t;
begin
 fpsetsid:=do_syscall(syscall_nr_setsid);
end;    
Ich sehe schon, mit Linux kann recht viele Sachen machen, nur bleibt einem sehr viel verborgen. :roll:
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Socke
Lazarusforum e. V.
Beiträge: 3158
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: setsid() – neue Sitzung erstellen (linux)

Beitrag von Socke »

Mathias hat geschrieben:
Mi 12. Jul 2023, 13:50
Was bei dem Beispiel noch interessant ist, Write wird ohne Probleme ausgeführt.
Das steht alles in der Manpage. Hier noch eine deutsche Übersetzung: https://manpages.ubuntu.com/manpages/fo ... ork.2.html

Beide Prozesse können Write(ln) ohne Probleme ausführen, da beide auf die selbe Datei (STDOUT) zugreifen. Wenn Prozess 1 diesen schließt oder die Konsole STDOUT in eine andere Datei umleitet, gilt das auch für Prozess 2. Da Netzwerkverbindungen auch nur Dateien sind, kann man das auch gut für Server-Anwendungen nutzen; der Apache Webserver nutzt fork üblicherweise unter Linux für jede eingehende Verbindung. In der Manpage Übersetzung heißt es ein wenig kompliziert.
man fork(2) hat geschrieben:Das Kind erbt Kopien der Menge der offenen Dateideskriptoren des Elternprozesses. Jeder
Deskriptor des Kindes bezieht sich auf die gleichen offenen Dateideskriptoren (siehe
open(2)) wie der entsprechende Dateideskriptor in dem Elternprozess. Dies bedeutet,
dass die beiden Dateideskriptoren die Statusschalter geöffneter Dateien, den
Datei-Offset und signalgesteuerte E/A-Attribute (siehe die Beschreibung von F_SETOWN
und F_SETSIG in fcntl(2)) gemeinsam nutzen.
Mathias hat geschrieben:
Mi 12. Jul 2023, 13:50
Sobald die hergestellt ist, stellt er mit fpfork eine Kopie her
Anscheinend schon eingebaut bei der Unit "baseunix".
Aber setsid etwas merkwürdig, anstelle eine C-lib Anbindung, wird eine function aufgerufen.

Code: Alles auswählen

function fpsetsid : pid_t;
begin
 fpsetsid:=do_syscall(syscall_nr_setsid);
end;    
Wie in deinem anderen Thread dargestellt, ruft dein Programm den Kernel direkt auf ohne die libc dafür nutzen zu müssen - das ist bei setsid genau so wie bei fork. Die Prozess-Kopie legt schließlich nicht die libc sondern das Betriebssystem an. Die libc-Funktion fork() leitet deinen Wunsch eigentlich nur an das Betriebssystem weiter.

Die libc stellt damit eine feste Schnittstelle zum Betriebssystem bereit, damit man nicht für jede Anwendung die Betriebssystemaufrufe (Sytem Call) neu programmieren muss. In Free Pascal übernimmt diese Aufgabe die Runtime Library (RTL) bzw. die Unit baseunix.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

Mathias
Beiträge: 6209
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: setsid() – neue Sitzung erstellen (linux)

Beitrag von Mathias »

Zum ursprünglichen Thema zurück.

setsid geht auch auf der Konsole.
ZB.

Code: Alles auswählen

setsid startlazarus
Startet lazarus, ohne das die Konsole blockiert.
Einziges Manko, wen das gestartet Programm Ausgaben hat, werden diese in die Konsole geschrieben.
Die kann zB. beim start von "fp" negative Auswirkungen haben.

Linux hat soviel interessante Sachen, welche mal leider nur per Zufall entdeckt,.
Leider findet man solche Sachen nicht in den Mainstream-PC-Zeitschriften.


Für Lazarus habe ich für setsid auch gerade eine praktische Anwendung gefunden.
Ein Prgoramm, das Daten fürs Clipboard zur Verfügung stellt. Und diese läuft solange im Hintergrund, bis ich bei einer anderen App Ctrl-C (Copy) drücke. Dann wird mein Hintergrund Programm beendet, weil ein Ereigniss ausgelöst wird.

Code: Alles auswählen

begin
  if fork <> 0 then begin
    setsid; // Startet den Klon
    WriteLn('ende');
    Halt; // Hauptprozesse beenden, so das wieder das Konsolenprompt erscheint.
  end else begin  
    main; // Stellt Daten im Hintergrund fürs Clipboard zu Verfügung.
  end;
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten