- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 10 von 13

Thema: PHP/RPi: 64 bit int-String auf 32bit-Hardware berechnen

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    42
    Beiträge
    2.009

    PHP/RPi: 64 bit int-String auf 32bit-Hardware berechnen

    Moin.

    Kleines Problem:
    Ich hab einen alten Raspberry Pi (einer der ersten, noch mit Wheezy), 32 bit, PHP5, keine GMP-Erweiterung. Updates gibts nicht mehr, da die ganzen online repos schon weg sind. Eine Änderung dieser Hardware sind technisch und wirtschaftlich bedingt nicht möglich oder sinnvoll. An diesem Pi hängen 14 (Archiv-)Festplatten, die über SSH ein/aus geschaltet werden können. Es ist also nur die Platte aktiv, deren Daten ich brauche. Über smartctl les ich von den Platten u.a. die Temperatur, Power On Hours etc. ein und lass mir das Ganze auf ner einfachen php-Seite anzeigen.
    Das alles funktioniert jetzt schon seit 8 Jahren.

    Hab jetzt aber schon 2 neue Festplatten dabei, wo der Wert für die Betriebsstunden unmöglich gross erscheint, z.B. 196889890783256. Da dieser Wert bis zu diesm Zeitpunkt ein String ist, kommt PHP noch damit klar, muss ja nichts gerechnet werden.
    Rechne ich das dann mit dem Windows Calc nach Hex um, kommt 0xB31200000018 raus. Diese 0x....18 wären dann 24 Stunden, das geht sich bei der neuen Platte auch sehr genau hin.
    Idee: Ich mach von diesem Wert einfach ein $val = $val & 0xFFFFFFFF, also hol mir nur die untersten 32 bit.
    Problem: Ich krieg da dann 0x7FFFFFFF raus, da PHP auf dem 32bit-Pi eben mit diesem riesigen Wert nicht klarkommt.

    Den Wert von smartctl direkt als hex kriegen geht scheinbar leider nicht, zumindest hab ich keine Option dazu gefunden.

    Wie könnte man jetzt auf einem 32bit-System von diesem 64bit-String nur die unteren 32bit behalten und den Rest verwerfen?
    24bit würden auch noch reichen.

    MfG
    Stefan
    #ifndef MfG
    #define MfG

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.650
    "von diesem 64bit-String nur die unteren 32bit behalten"

    196889890783256:

    a = 6
    a = a + (5*10)
    a = a + (2*100)
    a = a + (3*1000)
    ...

    Dazu müsste man die Zeichen einzeln aus dem String extrahieren.
    count_chars (Anzahl ermitteln) und str_split (den String in ein Array umwandeln)können dabei behilflich sein.

    MfG

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    42
    Beiträge
    2.009
    hm scheint nicht ganz das richtige zu sein.
    Angenommen ich würde das z.B. für nur 6 stellen machen. Also ....783256.

    Dann wäre das ja:
    a = 6
    a = a + (5*10)
    a = a + (2*100)
    a = a + (3*1000)
    a = a + (8*10000)
    a = a + (7*100000)

    echo $a => 783256

    Das wäre ja nur ne Alternative zu $a = (int) substr($val, -6);
    Den String so zerschneiden geht ja, solange diese Zahl kleiner als 0x7FFFFFFF ist.
    Aber: Es sind in diesen kleinen Dezimalstellen auch noch eben Werte der oberen 32bit drin.

    Im Orignal-Wert (0xB31200000018) ist ja z.B. Bit 33 gesetzt (0x000200000000, 8589934592)
    Wenn ich dann davon nur die letzten 6 Stellen nehme (934592) kann ich ohne Kenntnis der oberen 32bit eigentlich nichts sagen.

    Nehmen wir vereinfach einfach mal den ausgelesenen Wert (0x000200000002, 8589934594).
    Die unteren 32 bit sind 2, d.h. die Platte hätte 2 Stunden hinter sich.
    Aber nur aus den letzten Stellen der Dezimalzahl (934594) komm ich da nie auf die tatsächliche Laufzeit.

    Wenn ich nun weiss, dass 0x000200000000 = 8589934592, dann kann ich 934594 - 934592 rechnen und krieg die wirklichen 2.
    Kann ich aber nicht, da 0x000200000000 > 0x7FFFFFFF.

    Scheint also entweder tatsächlich nicht so ohne weiteres möglich zu sein, oder es ist so dermassen einfach, dass man's vor lauter denken nicht sieht.

    MfG
    #ifndef MfG
    #define MfG

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.650
    Hallo!

    Der Wert, den Du von smartctl als String bekommst, wie kommst Du an den Wert? Automatisch? Oder nur manuell? Was ist das genau für ein Wert, Sekunden, Stunden, Minuten? Und was möchtest Du daraus haben, Stunden, Minuten, Sekunden?

    Alles, was man mit einem Computersystem mathematisch nicht verarbeiten kann, weil der Wertebereich mit der vorhandenen Bitbreite nicht abgebildet werden kann, muss mathematisch so zerlegt werden, dass man damit arbeiten kann. Wie auch immer. Dabei ist auch das Ziel interessant. Zum Beispiel wegen der Genauigkeit. Sobald nur eine Manuelle Eingabe (oder eben ein String) vorhanden ist, muss der dann analysiert und sinnvoll zerlegt werden. Deswegen oben meine Fragen. Ich verstehe das nämlich noch nicht, was genau von was in was umgewandelt werden sollte. Man kann auch Hex-Werte, die als String vorliegen, zerlegen und umwandeln.
    Ich habe leider in PHP auch erst einmal keine Funktion gefunden, welche die Arbeit abnehmen könnte. Deswegen gehe ich in solchen Fällen den mühseligeren Weg, der aber irgendwie immer funktioniert.

    (0x000200000002, 8589934594)
    Die unteren 32 bit sind 2, d.h. die Platte hätte 2 Stunden hinter sich.
    Aber nur aus den letzten Stellen der Dezimalzahl (934594) komm ich da nie auf die tatsächliche Laufzeit.


    Was ist mit dem Hex-Wert -
    0x000200000002 ? Ist das der originale Wert, wie er sein soll, weil die letzte "2" 2 Stunden representiert? Und Du bekommst aber nicht den Hex-Wert, sondern nur den entsprechenden Wert in Dezimalschreibweise und das als String?


    Das wäre ja nur ne Alternative zu $a = (int) substr($val, -6);
    Den String so zerschneiden geht ja, solange diese Zahl kleiner als 0x7FFFFFFF ist.


    Ja. Wird die Zahl größer muss die Rechnung dann zerlegt werden. In einen höherwertigen Teil und einen niederwertigen Teil. So, wie bei 0x1234. Ist ja eigentlich ein 16 Bit-Wert. Angenommen, deine CPU kann aber nur 8 Bit. Dann kann man das zerlegen in 0x12 und 0x34. Mit diesen beiden Teilen kann man weiter rechnen, th. beliebig große Zahlen.


    Geändert von Moppi (11.10.2021 um 16:55 Uhr)

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    42
    Beiträge
    2.009
    Moin.

    Ich führ in einem PHP-Skript den Aufruf für alle gemounteten Platten nacheinander aus mit:

    Code:
      $cmdSmart = "sudo -u root /usr/sbin/smartctl -A $device -d sat 2>&1";
      $resultSmart = shell_exec($cmdSmart);
    In $resultSmart geh ich dann Zeilenweise durch und hol mir die interessanten Werte (Power On Hours, Start Stop Count, Temperature)
    Da ich die Werte einfach nur als String einlese und auf ner Webseite anzeige, musste ich auch nicht wirklich rechnen.
    Lediglich bei der Temperatur gibts Warnungen, wenns zu heiss wird. Aber das sind Werte, die ich mit 6 bit auch schaffen würde.


    Die Ausgabe sieht z.B. so aus für eine schon ältere Platte mit 10931 Betriebsstunden (ID 9):

    Code:
    ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
      1 Raw_Read_Error_Rate     0x002f   200   200   051    Pre-fail  Always       -       0
      3 Spin_Up_Time            0x0027   172   170   021    Pre-fail  Always       -       2383
      4 Start_Stop_Count        0x0032   099   099   000    Old_age   Always       -       1931
      5 Reallocated_Sector_Ct   0x0033   200   200   140    Pre-fail  Always       -       0
      7 Seek_Error_Rate         0x002e   100   253   000    Old_age   Always       -       0
      9 Power_On_Hours          0x0032   086   086   000    Old_age   Always       -       10931
     10 Spin_Retry_Count        0x0032   100   100   000    Old_age   Always       -       0
     11 Calibration_Retry_Count 0x0032   100   100   000    Old_age   Always       -       0
     12 Power_Cycle_Count       0x0032   099   099   000    Old_age   Always       -       1825
    192 Power-Off_Retract_Count 0x0032   198   198   000    Old_age   Always       -       1804
    193 Load_Cycle_Count        0x0032   200   200   000    Old_age   Always       -       126
    194 Temperature_Celsius     0x0022   120   088   000    Old_age   Always       -       23
    196 Reallocated_Event_Count 0x0032   200   200   000    Old_age   Always       -       0
    197 Current_Pending_Sector  0x0032   200   200   000    Old_age   Always       -       0
    198 Offline_Uncorrectable   0x0030   200   200   000    Old_age   Offline      -       0
    199 UDMA_CRC_Error_Count    0x0032   200   200   000    Old_age   Always       -       12
    200 Multi_Zone_Error_Rate   0x0008   200   200   000    Old_age   Offline      -       0
    Und das ist eine der neuen mit einem "unmöglichen" Wert 168598941204504 = 0x995700000018, "unten" 0x18 = 24 Betriebsstunden.
    Was das in den vorderen 32Bit (bzw. 16) ist, keine Ahnung, aber wechselt bei jedem Auslesen scheinbar willkürlich. Hab da noch kein Muster feststellen können.
    Vorher: 196889890783256 0xB31200000018
    Jetzt: 168598941204504 0x995700000018

    Code:
    ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
      1 Raw_Read_Error_Rate     0x000f   074   073   006    Pre-fail  Always       -       24503642
      3 Spin_Up_Time            0x0003   099   099   000    Pre-fail  Always       -       0
      4 Start_Stop_Count        0x0032   100   100   020    Old_age   Always       -       6
      5 Reallocated_Sector_Ct   0x0033   100   100   010    Pre-fail  Always       -       0
      7 Seek_Error_Rate         0x000f   065   060   045    Pre-fail  Always       -       2896370
      9 Power_On_Hours          0x0032   100   100   000    Old_age   Always       -       168598941204504
     10 Spin_Retry_Count        0x0013   100   100   097    Pre-fail  Always       -       0
     12 Power_Cycle_Count       0x0032   100   100   020    Old_age   Always       -       6
    183 Runtime_Bad_Block       0x0032   100   100   000    Old_age   Always       -       0
    184 End-to-End_Error        0x0032   100   100   099    Old_age   Always       -       0
    187 Reported_Uncorrect      0x0032   100   100   000    Old_age   Always       -       0
    188 Command_Timeout         0x0032   100   100   000    Old_age   Always       -       0
    189 High_Fly_Writes         0x003a   100   100   000    Old_age   Always       -       0
    190 Airflow_Temperature_Cel 0x0022   073   057   040    Old_age   Always       -       27 (Min/Max 25/27)
    191 G-Sense_Error_Rate      0x0032   100   100   000    Old_age   Always       -       0
    192 Power-Off_Retract_Count 0x0032   100   100   000    Old_age   Always       -       4
    193 Load_Cycle_Count        0x0032   100   100   000    Old_age   Always       -       91
    194 Temperature_Celsius     0x0022   027   043   000    Old_age   Always       -       27 (0 25 0 0)
    195 Hardware_ECC_Recovered  0x001a   074   073   000    Old_age   Always       -       24503642
    197 Current_Pending_Sector  0x0012   100   100   000    Old_age   Always       -       0
    198 Offline_Uncorrectable   0x0010   100   100   000    Old_age   Offline      -       0
    199 UDMA_CRC_Error_Count    0x003e   200   200   000    Old_age   Always       -       0
    240 Head_Flying_Hours       0x0000   100   253   000    Old_age   Offline      -       126937758433301
    241 Total_LBAs_Written      0x0000   100   253   000    Old_age   Offline      -       1932648833
    242 Total_LBAs_Read         0x0000   100   253   000    Old_age   Offline      -       3374992
    Und die Werte werden eben leider nur dezimal angezeigt. Wären das Hex-Werte, wäre das Problem keins mehr. Dann würd ich nur die letzten 8 Hex-"Ziffern" einlesen und gut. Nur akzeptiert dieses smartctl den Parameter "hex,val" nicht für -f, sondern nur "old" und "brief".
    Update-Versuch dieses einen Pakets: "smartmontools ist schon die neueste Version", weils für den alten Hobel nichts mehr gibt.

    Das mit 0x000200000002 war nur mal ein Beispiel, dass eben auch die 2 in den oberen 32 Bit da quasi "stört".


    MfG
    Stefan
    #ifndef MfG
    #define MfG

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.650
    Schau mal hier rein, ob das nützlich ist: https://www.php.net/manual/de/function.dechex.php

    // Input: A decimal number as a String.
    // Output: The equivalent hexadecimal number as a String.

    Freundlichen Gruß

Ähnliche Themen

  1. 32Bit Zahl in BCD umwandeln
    Von rogerberglen im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 9
    Letzter Beitrag: 30.01.2013, 19:01
  2. 32bit Multiplizierer - Was bedeutet die 32?
    Von Asuroneuling im Forum Elektronik
    Antworten: 9
    Letzter Beitrag: 11.02.2010, 12:33
  3. string an lcd senden, string in pointer speichern
    Von andi.studi im Forum PIC Controller
    Antworten: 15
    Letzter Beitrag: 14.08.2008, 00:51
  4. 32bit Schieberegister Ansteuerung...Wo ist der Fehler?
    Von KonZ im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 21.09.2007, 09:27
  5. String auf String zuweisen geht nicht
    Von Jaecko im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 6
    Letzter Beitrag: 14.12.2006, 18:48

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen