Warum gibt getpid() pid_t statt int zurück?

Lesezeit: 8 Minuten

Benutzeravatar von ntl0ve
ntl0ve

Wie ist die Logik hinter Anrufen? getpid() einen Wert vom Typ zurückgeben pid_t statt ein unsigned int? Oder int? Wie hilft das?

Ich vermute, das hat mit der Portabilität zu tun? Das garantieren pid_t ist die gleiche Größe auf verschiedenen Plattformen, die unterschiedliche Größen haben können ints usw.?

Ich denke, es ist das Gegenteil: das Programm über Plattformen portierbar zu machen, unabhängig davon, ob zB eine PID 16 oder 32 Bit (oder sogar länger) ist.

  • Die Untertypisierung von Ganzzahlen jenseits von xiint8_t xint16_t xint32_t xint64_t löst keine Probleme: Es gibt automatische Ganzzahlkonvertierungen. Daher enthält jedes reale Programm mit angemessenem Alter (z. B. 10 Jahre) und Größe (z. B. 1 MLOC) Tausende von nicht nachweisbaren stillen Annahmen über ganzzahlige Größen.

    – uuu777

    8. August 2017 um 12:40 Uhr

Der Grund dafür ist, dass böse historische Implementierungen immer noch konform bleiben. Angenommen, Ihre historische Implementierung hatte (ziemlich häufig):

short getpid(void);

Natürlich wollen moderne Systeme, dass PIDs mindestens 32-Bit sind, aber wenn der Standard es vorschreibt:

int getpid(void);

dann alle historischen Implementierungen, die verwendet wurden short nicht konform werden würde. Dies wurde als inakzeptabel erachtet, so pid_t erstellt wurde und die Umsetzung durfte definiert werden pid_t welchen Weg es bevorzugt.

Beachten Sie, dass Sie keineswegs zur Nutzung verpflichtet sind pid_t in Ihrem eigenen Code, solange Sie einen Typ verwenden, der groß genug ist, um jede PID (intmax_t würde zum Beispiel gut funktionieren). Der einzige Grund pid_t muss existieren ist Sache des Standards zu definieren getpid, waitpidetc. in Bezug darauf.

  • Ach, Maßstäbe. Ich habs. Aber was ist mit Stil/Best Practice? Ist es besser zu verwenden pid_t als ein int für das halten einer pid? In Bezug auf die Lesbarkeit (in Anspielung auf die Antwort von @Maz)? Oder ist es so trivial und bedeutungslos, dass es diese Art von Aufmerksamkeit nicht verdient?

    – ntl0ve

    11. September 2011 um 14:53 Uhr

  • Wenn ich doppelt abstimmen könnte … aber die Antwort von zvrbas ist eine Art komprimierte Version dieser Antwort, also werde ich auch zvrba positiv bewerten.

    – Prof. Falken

    11. September 2011 um 14:53 Uhr

  • Verwenden int ist wahrscheinlich keine gute Idee, da es hypothetische zukünftige Implementierungen mit 64-Bit-PIDs nicht unterstützen würde. Ich würde einfach verwenden pid_t für die meisten Anwendungen, aber denken Sie daran, dass, wenn Sie eine Datenstruktur haben, die “generische Ganzzahlen” mit einem großen Typ (z intmax_t) wäre es akzeptabel, PIDs auf diese Weise zu speichern.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    11. September 2011 um 15:17 Uhr

  • Ein besseres Beispiel für einen “nutzlosen” Typ wäre socklen_t die aus dem gleichen Grund hinzugefügt wurde (Uneinigkeit darüber, ob bestimmte Funktionen übernommen werden sollen int oder size_t Argumente).

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    11. September 2011 um 15:18 Uhr

Auf verschiedenen Plattformen und Betriebssystemen können verschiedene Typen (z. B. pid_t) 32 Bit (unsigned int) auf einem 32-Bit-Computer oder 64 Bit (unsigned long) auf einem 64-Bit-Computer sein. Oder ein Betriebssystem entscheidet sich aus einem anderen Grund für eine andere Größe. Außerdem wird beim Lesen des Codes deutlich, dass diese Variable ein “Objekt” darstellt und nicht nur eine beliebige Zahl.

  • fork() kehrt zurück -1 bei Misserfolg, also pid_t muss ein vorzeichenbehafteter ganzzahliger Typ sein.

    – Przemek

    17. Juni 2018 um 19:56 Uhr

Justin Time - Stellen Sie Monicas Benutzeravatar wieder her
Justin Time – Wiedereinsetzung von Monica

Der Zweck ist es zu machen pid_t, oder jede andere Art dieser Art, plattformunabhängig, sodass sie unabhängig davon, wie sie tatsächlich implementiert ist, ordnungsgemäß funktioniert. Diese Vorgehensweise wird für jeden Typ verwendet, der plattformunabhängig sein muss, z. B.:

  • pid_t: Muss groß genug sein, um eine PID auf dem System zu speichern, für das Sie codieren. Karten zu int soweit mir bekannt ist, obwohl ich mit der GNU C-Bibliothek nicht am vertrautesten bin.
  • size_t: Ein unsigned Variable, die das Ergebnis der speichern kann sizeof Operator. Im Allgemeinen gleich groß wie die Wortgröße des Systems, für das Sie codieren.
  • int16_t (intX_t): Muss unabhängig von der Plattform genau 16 Bit sein und wird nicht auf Plattformen definiert, die 2 nicht verwendenn-Bit-Bytes (normalerweise 8- oder 16-Bit) oder bieten, viel seltener, eine Möglichkeit, auf genau 16 Bits eines größeren Typs zuzugreifen (z. B. die “Bytes” des PDP-10, die eine beliebige Anzahl zusammenhängender Bits sein können). aus einem 36-Bit-Wort und könnten daher genau 16 Bits sein) und unterstützen daher keine 16-Bit-Zweierkomplement-Ganzzahltypen (z. B. ein 36-Bit-System). Im Allgemeinen Karten zu short auf modernen Computern, obwohl es eine sein kann int auf ältere.
  • int_least32_t (int_leastX_t): Muss die kleinstmögliche Größe sein, die mindestens 32 Bit speichern kann, z. B. 36 Bit auf einem 36-Bit- oder 72-Bit-System. Im Allgemeinen Karten zu int auf modernen Computern, obwohl es eine sein kann long auf ältere.
  • int_fastX_t: Muss der schnellstmögliche Typ sein, der mindestens X Bits speichern kann. Im Allgemeinen ist es die Wortgröße des Systems, wenn (X <= word_size) (oder manchmal char zum int_fast8_t) oder wirkt wie int_leastX_t wenn (X > word_size))
  • intmax_t: Muss die maximale Ganzzahlbreite sein, die vom System unterstützt wird. Im Allgemeinen sind es auf modernen Systemen mindestens 64 Bit, obwohl einige Systeme möglicherweise erweiterte Typen unterstützen, die größer sind als long long (und wenn, intmax_t muss der größte dieser Typen sein).
  • Und mehr…

Mechanisch ermöglicht es das Installationsprogramm des Compilers typedef den passenden Typ zum Bezeichner (ob ein Standardtyp oder ein ungeschickt benannter interner Typ) hinter den Kulissen, sei es durch das Erstellen geeigneter Header-Dateien, das Codieren in die ausführbare Datei des Compilers oder eine andere Methode. Beispielsweise implementiert Microsoft Visual Studio auf einem 32-Bit-System die intX_t und ähnliche Typen wie folgt (Anmerkung: Kommentare von mir hinzugefügt):

// Signed ints of exactly X bits.
typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;

// Unsigned ints of exactly X bits.
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;

// Signed ints of at least X bits.
typedef signed char int_least8_t;
typedef short int_least16_t;
typedef int int_least32_t;

// Unsigned ints of at least X bits.
typedef unsigned char uint_least8_t;
typedef unsigned short uint_least16_t;
typedef unsigned int uint_least32_t;

// Speed-optimised signed ints of at least X bits.
// Note that int_fast16_t and int_fast32_t are both 32 bits, as a 32-bit processor will generally operate on a full word faster than a half-word.
typedef char int_fast8_t;
typedef int int_fast16_t;
typedef int int_fast32_t;

// Speed-optimised unsigned ints of at least X bits.
typedef unsigned char uint_fast8_t;
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;

typedef _Longlong int64_t;
typedef _ULonglong uint64_t;

typedef _Longlong int_least64_t;
typedef _ULonglong uint_least64_t;

typedef _Longlong int_fast64_t;
typedef _ULonglong uint_fast64_t;

Auf einem 64-Bit-System müssen sie jedoch nicht unbedingt auf die gleiche Weise implementiert werden, und ich kann garantieren, dass sie auf einem archaischen 16-Bit-System nicht auf die gleiche Weise implementiert werden, vorausgesetzt, Sie finden eine MSVS-kompatible Version mit einer.

Insgesamt ermöglicht es Code, unabhängig von den Besonderheiten Ihrer Implementierung ordnungsgemäß zu funktionieren und die gleichen Anforderungen auf jedem standardkompatiblen System (z pid_t garantiert groß genug sein, um jede gültige PID auf dem betreffenden System zu speichern, egal für welches System Sie codieren). Es verhindert auch, dass Sie das Wesentliche kennen und interne Namen nachschlagen müssen, mit denen Sie möglicherweise nicht vertraut sind. Kurz gesagt, es stellt sicher, dass Ihr Code unabhängig davon, ob pid_t (oder jede andere ähnliche Typedef) wird als implementiert inta shorta longa long longoder sogar ein __Did_you_really_just_dare_me_to_eat_my_left_shoe__also musst du nicht.


Darüber hinaus dient es als Dokumentation, sodass Sie auf einen Blick erkennen können, wozu eine bestimmte Variable dient. Folgendes berücksichtigen:

int a, b;

....

if (a > b) {
    // Nothing wrong here, right?  They're both ints.
}

Jetzt versuchen wir es noch einmal:

size_t a;
pid_t b;

...

if (a > b) {
    // Why are we comparing sizes to PIDs?  We probably messed up somewhere.
}

Wenn es als solches verwendet wird, kann es Ihnen helfen, potenziell problematische Codesegmente zu lokalisieren, bevor etwas kaputt geht, und die Fehlerbehebung viel einfacher machen, als es sonst der Fall wäre.

Jeder Prozess im Programm hat eine bestimmte Prozess-ID. Durch den Aufruf von pid kennen wir die zugewiesene ID des aktuellen Prozesses. Die Kenntnis der pid ist bei der Verwendung außerordentlich wichtig fork()weil es zurückkehrt 0 und !=0 Werte für untergeordnete und übergeordnete Kopien rezeptiv. Diese beiden Videos haben klare Erklärungen: Video Nr. 1 Video Nr. 2

Ein Beispiel: Angenommen, wir haben das folgende C-Programm:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>


int main (int argc, char *argv[])
{

  printf("I am %d\n", (int) getpid());
  pid_t pid = fork();
  printf("fork returned: %d\n", (int) pid);
  if(pid<0){
    perror("fork failed");
  }
  if (pid==0){
    printf("This is a child with pid %d\n",(int) getpid());
  }else if(pid >0){
    printf("This is a parent with pid %d\n",(int)getpid());
  }

  return 0;
}

Wenn Sie es ausführen, erhalten Sie 0 für Kind und nicht zero/greater than zero für die Eltern.

Benutzeravatar von 0xcurb
0xBordstein

Eine Sache, auf die ich hinweisen sollte, in den meisten Antworten sah ich etwas in der Art von
“Durch die Verwendung von pid_t funktioniert der Code auf verschiedenen Systemen”was nicht unbedingt stimmt.

Ich glaube, der genaue Wortlaut sollte lauten: Es lässt den Code auf verschiedenen Systemen ‘kompilieren’.

Wenn Sie beispielsweise den Code auf einem System kompilieren, das 32-Bit-pid_t verwendet, wird eine Binärdatei erzeugt, die dies tut wahrscheinlich Break, wenn es auf einem anderen System ausgeführt wird, das 64-Bit-pid_t verwendet.

1411200cookie-checkWarum gibt getpid() pid_t statt int zurück?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy