1. BENVENUTO SU CONSOLE TRIBE

    Benvenuto, stai navigando nella nostra community come ospite

    Avere un account su Console Tribe ti permetterà di creare e partecipare alle discussioni e al mercatino, organizzare tornei e partite online, iniziare conversazioni personali con gli altri giocatori del forum e di utilizzare tutte le funzioni di questo sito.

    Registra il tuo account in meno di 5 secondi, se vuoi puoi sfruttare i login social via Facebook, Google Plus o Twitter.

XBox non moddata, 007 e Live! senza mai farsi prendere da Microsoft

Discussione in 'Xbox Live!' iniziata da ConteZero, 11 Ottobre 2003.

  1. ConteZero

    ConteZero Tribe Member

    Registrato:
    16 Marzo 2005
    Messaggi:
    7.682
    "Mi Piace" ricevuti:
    1
    Punteggio:
    36
    Vedo che non sei molto ferrato in informatica:

    Multitasking
    Codici completamente disgiunti, originati probabilmente da file eseguibili diversi, in esecuzione contemporaneamente in Time sharing.
    Ogni processo ha uno spazio di indirizzamento DISGIUNTO dagli altri processi e comunica con gli altri via IPC.

    Multithreading
    Stesso codice, su cui girano più thread, lo spazio d'indirizzamento è comune e i thread comunicano fra di loro usando principalmente la memoria.
    I thread condividono tutti lo stesso codice.
    I thread (o Task Lightweight) si dividono in User Thread (detti Fiber su Windows) che sono l'implementazione completamente in userspace di cui il kernel non è a conoscenza e Kernel Thread (detti Thread sotto Windows) che sono l'implementazione con codice in Kernel space, la differenza è che i Kernel Thread sono meno flessibili ma virtualmente più facili da gestire mentre la versione User richiede più lavoro in quanto bisogna lavorare con system call non bloccanti in un ambito di multiprocessing cooperativo.

    Per capirci un thread è simile (anche se non è) il FORK di Unix/Linux, ti crea un altro "flusso esecutivo" parallelo al generante, ambedue in esecuzione sullo stesso codice, se vuoi caricare un altro frammento di codice e farlo eseguire al processo generato questo è IN GENERALE possibile ma non ci sono le funzionalità nel kernel per automatizzare il processo e utilizzare i thread per fare i multitasking è una cosa che è A DIR POCO sconsigliabile.

    Vatti a leggere qualche testo di Andrew Tanenbaum.
  2. TheHutcher

    TheHutcher <font color=#00FF33><b> Il Miglior Amico di Gogy <

    Registrato:
    16 Dicembre 2002
    Messaggi:
    3.604
    "Mi Piace" ricevuti:
    0
    Punteggio:
    36
    A parte leggere (male) un testo che hai trovato in giro, vedo che non sei proprio andato a vedere come funziona la XBox....
    Leggiti Tanenbaum, quando avrai capito qualcosa fammelo sapere.... E sopratutto quando avrai combinato qualcosa fallo sapere a tutti, in modo da dimostrare cosa capisci tu di informatica.....

    Se vuoi continuare il 3D accomodati, io comincio a sbadigliare a causa della tua scarsa consistenza.... Chiederò a GoGy di rispondere al posto mio, non dovresti notare grosse differenze :D
    Ciao
  3. ConteZero

    ConteZero Tribe Member

    Registrato:
    16 Marzo 2005
    Messaggi:
    7.682
    "Mi Piace" ricevuti:
    1
    Punteggio:
    36
    Allora
    apparte il fatto che sistemi operativi l'ho passato l'anno scorso con 30 e lode proprio su un testo del Tanenbaum (no, non Sistemi Operativi, quello lo leggo a tempo perso per divertimento personale) vorrei sapere cosa intendi tu per task e thread visto che non mi pare che apparte sparare a zero tu sappia fare molto altro.

    Eccoti quindi una spiegazione veloce:

    Per gestire al meglio la potenza di calcolo di un processore si è pensato di permettere l'esecuzione concorrente di diversi processi indipendenti, la contemporaneità è stata utile in quanto ogni processo ha dei tempi morti dovuti, ad esempio, a delle fasi di I/O o a delle attese, in quel periodo l'attesa passiva rappresenta una grossa perdita di tempo.
    Il processo in verità è stato discretamente pesante ed ha seguito l'evoluzione sia delle architetture dei processori (indicando spesso cos'è necessario e quando, vedi la TSL) sia dei modelli di memoria; si è passati da sistemi batch capaci di eseguire solo un processo alla volta in modo strettamente sequenziale a memoria nè paginata nè segmentata al modello attuale che, con le dovute limitazioni, è considerabile come ottimale.
    In pratica si è pensato che il massimo delle prestazioni si ottenga mantenedo la CPU occupata il più a lungo possibile e questo si ottiene semplicemente utilizzando degli accorgimenti (che richiedono sia funzionalità hardware che codice apposito nel S.O.) che permettono di "congelare" lo stato in cui si trova un processo quando quest'ultimo è in "attesa" salvando lo stato del processore in un area apposita (detta PCB, Process Control Block secondo la nomenclatura IBM) per "riesumare" lo stato di un altro processo, recuperando lo stato di questi dal PCB del processo stesso.
    Questa operazione, che è invero discretamente più complessa, è quella che prende canonicamente il nome di "task switch" ed è tristemente nota per rappresentare overhead puro, ovvero "consumo della risorsa (cicli del processore) senza produrre effettivamente "lavoro".
    Ovviamente ci sono altri motivi che possono produrre un task switch, come alcune interruzioni, eccezioni o chiamate esplicite ma non voglio entrare nel merito per adesso.
    I sistemi "semplici" non hanno altro meccanismo di switch, si limitano a eseguire lo "scheduler" (il codice che determina il processo che verrà eseguito e vi passa il controllo) ogni qual volta un processo si trova a dover effettuare un operazione che richiede interventi asincroni (come l'I/O o un IPC); per la precisione in passato si è parlato anche di multitasking cooperativo indicando "bonariamente" un sistema del tutto simile a quello sopra esposto in cui è però il processo che si pone in attesa a "indicare" il suo successore esplicitamente tramite una chiamata apposita (la cosiddetta "Yield" se ricordo bene).
    Fino a qui nessun problema, il problema si è presentato quando si è visto che alcuni processi passano molto tempo a fare calcoli e calcoli senza mai ricorrere a chiamate di sistema (e quindi senza mai dare spazio ad altri processi), per questo motivo è stato considerato anche un altro meccanismo, quello di preemption, ovvero il prerilascio forzato della risorsa processore.
    In pratica la preemption è un meccanismo (che si basa su un componente hardware indipendente, un clock) (= un generatore di interrupt a intervalli regolari e fissi) che permette una distribuzione equa della risorsa processore in unità dette quanti.
    Il quanto di tempo è il tempo che intercorre fra un interrupt ed un altro, su un PC standard questo intervallo è regolabile ma è, in genere, fissato a 1/18 di secondo circa.
    In pratica ogni diciottesimo di secondo il processo in esecuzione viene fermato (se non sta effettuando operazioni critiche) (solo un NMI è più forte di un istruzione CLI) (non badateci, non voglio entrare nel merito delle architetture) e vengono fatte delle considerazioni relative a quanti quanti questo processo ha girato e qual'è la sua priorità.
    Il frammento di codice che valuta questi dati (lo scheduler di BASSO livello) decide se effettuare un context switch oppure se far riprendere il processo in esecuzione al momento dell'interrupt.
    L'utilizzo congiunto di un sistema di preemption e l'introduzione del concetto di PRIORITA' (specificatamente nel caso in cui un IPC sblocca un processo con priorità maggiore) sono la definizione di un sistema preemptive.
    Piccola nota, avete notato in che termini ho parlato di blocco del processo in esecuzione e di ripresa ed ho parlato di context switch ?
    Il context switch è un operazione estremamente lunga e laboriosa, i cui tempi sono molto lunghi (ben oltre quelli esplicitati nei datasheet, tutto il sistema delle cache e dei TLB viene "duramente messo alla prova" quando avviene un context switch richiedendo migliaia di cicli per il flush delle cache) e che vorremmo limitare al minimo; il context switch è comunque poco piacevole per un motivo che spiegheremo a seguire.
    In origine su un computer girava un solo programma alla volta, in quel caso era tutto facile, chi scriveva il codice poteva decidere arbitrariamente dove mettere il codice ed i dati senza preoccuparsi di possibili altri processi in esecuzione.
    Quando si è passati a sistemi più raffinati ci si è trovati davanti a un grosso problema: due (o più) processi qualsiasi potevano essere in memoria nello stesso istante.
    Dov'è il problema?
    Beh, come due corpi non possono occupare lo stesso spazio contemporaneamente non è pensabile neppure di mettere due programmi negli stessi indirizzi di memoria... e allora?
    Le prime soluzioni rudimentali si sono basate su quello che viene detto "rilocazione a load time", in pratica quando il programma viene caricato in memoria a partire dall'indirizzo X (<- dove c'è spazio libero in memoria) si cercano tutte le istruzioni che fanno riferimento diretto alla memoria e gli si aggiunge X.
    In seguito ci si è resi conto che se ci sono in esecuzione tre o piu processi: A, B e C e B termina magari sommando lo spazio liberato da B e quello dopo C ci sarebbe spazio per eseguire D ma, non essendoci abbastanza memoria "contigua" (consecutiva) il sistema tende a degradarsi a poco a poco che nuove applicazioni vengono lanciate e terminano.
    In quel periodo cominciavano inoltre ad apparire i primi problemi di sicurezza, visto che la CPU poteva indirizzare tutta la memoria in teoria un processo poteva leggere o sovrascrivere l'area dove risiedeva un altro processo.
    Per impedirlo è stato introdotto nelle CPU il concetto di "modalità utente" e "modalità supervisore".
    Nei processori del tempo erano presenti due registri, detti base e limite che delimitavano l'inizio e la fine dell'area in cui la CPU in "modalità utente" poteva leggere o scrivere, qualsiasi tentativo di oltrepassare quei limiti provocava un eccezione (ovvero una richiesta di interruzione invocata dalla CPU stessa) che portava la CPU in modalità supervisore e le faceva eseguire un codice "proprio" del sistema operativo che in genere terminava il processo "espansivo".
    Come si vede già allora lo stato del registro comincia a riempirsi di registri specializzati.
    Il problema dello spazio è stato in parte risolto passando a un modello più pratico che è la base dei segmenti, in pratica se il codice viene memorizzato a partire da X ed è lungo Y bytes nei registri base e limite vengono messi esattamente questi valori, quando la CPU passa in modalità utente la CPU effettua automaticamente la traduzione degli indirizzi cosicchè un Ind generico diventa Ind + Base; questo fa sì che virtualmente tutto il codice inizi dall'indirizzo 0: la soluzione dei buchi di memoria è affidata a una routine del sistema operativo che ogni N secondi prende il controllo della CPU e sposta (riloca) i processi in modo da eliminare i buchi e "corregge" i valori di BASE presenti nei PCB dei processi interessati.
    Il passo successivo è stato il passaggio alla paginazione la cui discussione rimando a ben altri luoghi, basti sapere che la paginazione elimina l'onere della rilocazione (pack) della memoria ma richiede un "complicato" sistema di registri e tabelle di cui il programmatore delle applicazioni non è al corrente.
    La paginazione è un compito oneroso per le CPU e quindi, per ottenere una resa dignitosa, molte cose sono bufferizzate in apposite cache specializzate (vedasi la TLB); sfortunatamente queste cache sono significative solo per il processo in esecuzione al momento per cui il passaggio da un processo ad un altro richiede tanto la riscrittura delle tabelle modificate in memoria centrale quanto l'invalidazione completa di tutti questi registri.

    Il proseguio domani, appena mi sveglio, sono troppo stanco per continuare stasera.
    Nota: non ho detto TUTTO, ho solo enunciato (semplificando ENORMEMENTE) qualche concetto legato ai sistemi operativi; sono disponibile a discutere argomenti correlati se me ne viene fatta esplicita richiesta in questo "3D".
  4. zell1983

    zell1983 Tribe Member

    Registrato:
    22 Settembre 2007
    Messaggi:
    292
    "Mi Piace" ricevuti:
    0
    Punteggio:
    16
    Non sono riuscito a leggerlo tutto... stavo schizzando :eek:
    Quando dovrò dare SO magari ci dò una letta :D
    Cmq sia a spiegare ste cose e a continuare a scrivere roba che la gente non capisce (vedi me),mi sembra un pò inutile,anche perchè pare che nessuno a parte ConteZero sia in grado di realizzarla...
    L'idea di base ce l'avevo,ora invece sono proprio nella confusione + totale... :strano:
    vabbè ... :D
  5. ConteZero

    ConteZero Tribe Member

    Registrato:
    16 Marzo 2005
    Messaggi:
    7.682
    "Mi Piace" ricevuti:
    1
    Punteggio:
    36
    Con l'andare del tempo e il raffinamento dei compilatori e delle tecniche di sviluppo del software si è fatta strada l'idea di sviluppare codice utilizzando non uno ma più cicli esecutivi (task) che comunicano fra loro.
    All'inizio questo genere di lavoro si faceva utilizzando processi disgiunti che operavano in spazi d'indirizzamento separati e comunicavano fra loro via IPC (Inter Process Communications, delle chiamate al sistema operativo in kernel space che passano i messaggi fra i processi),
    Purtoppo il ricorso all'IPC è molto penalizzante in quanto anche il passaggio da user mode a supervisor mode richiede un enorme dispendio di cicli (che è overhead puro) e la cosa è molto scomoda quando la dimensione dei messaggi da passare cresce; per questo e per altri motivi si è ipotizzato di far girare nello stesso codice diversi "flussi esecutivi" (thread).
    Per far ciò all'inizio, quando ancora i kernel dell'epoca non contemplavano un supporto per questo genere di cose, sono state utilizzate delle librerie che implementano delle API basate su system call non bloccanti (ovvero che non bloccano il processo in esecuzione quando invocate e non aspettano il completamento); quando un "flusso esecutivo" effettuava una di queste system call il codice effettuava la chiamata e subito dopo entrava in un ciclo di due istruzioni, la Yield (che diceva allo scheduler di passare l'esecuzione ad un altro flusso esecutivo all'interno dello stesso processo) ed il check (che controllava quando la system call aveva effettivamente finito il suo lavoro).
    Come si può vedere il passaggio da un ciclo esecutivo all'altro all'interno del processo richiede comunque una specie di context switch ma ad esserne interessati sono solo i registri generali accessibili in user space, tutto quel che riguarda gestione della protezione della memoria, cache e TLB non viene intaccato da questo context switch "lite", il kernel della macchina addirittura non si accorge e non ha modo di sapere se e quanti flussi esecutivi sono in esecuzione contemporaneamente per processo.
    I diversi flussi esecutivi comunicano e si sincronizzano in maniera veloce usando delle variabili di riferimento.
    Questa prima implementazione è quella dei thread in userspace che ha delle limitazioni, se un thread non effettua delle system call per lungo tempo gli altri thread sono sempre in attesa di essere eseguiti.
    Da qui la necessità di estendere il concetto di Thread all'interno del kernel stesso, in pratica il kernel viene modificato in modo da non schedulare più i processi ma direttamente i thread, ad ogni context switch effettuato dal kernel a parità di priorità vengono scelti thread appartenenti allo stesso processo e quando il context switch avviene fra thread dello stesso processo vengono aggiornati solo i valori relativi all'userspace evitando di invalidare le cache e di mettere mano ai registri di memoria.

    A questo punto la differenza fra thread e processi è discretamente semplice (mi pare) anche se ho fatto diverse semplificazioni per rendere la cosa fruibile a un più ampio numero di persone.
    Come puoi vedere la differenza fra thread e processi è abissale, i processi hanno spazi d'indirizzamento disgiunti e comunicano via IPC mentre i thread sono diversi flussi esecutivi all'interno dello stesso spazio d'indirizzamento.
    Il modello di memoria e di processore che usa l'xbox è un modello a ring0 (in pratica una sorta di supervisor mode) senza paginazione, la paginazione è resa inutile dall'ipotesi che sull'xbox ci sia in esecuzione al più un processo alla volta e quindi non c'è bisogno di separare gli spazi d'indirizzamento, inolte non essendo previsto un supporto per la memoria virtuale la paginazione diventa qualcosa di inutile e discretamente pesante da gestire (oltre che rallentare la traduzione degli indirizzi).
    Ovviamente nulla vieta ad un processo in esecuzione di caricare del codice in un area di memoria e farvi iniziare un thread, l'unico problema è che non c'è supporto nei framework per questo genere di operazioni (il che in pratica vuol dire che compilare quel codice diventa un incubo a meno che tu non mangi pane e assembly ed abbia tanto termpo libero).
    Inoltre il far eseguire un thread che è in effetti un processo è sconveniente perchè un qualsiasi bug nel codice "eseguito a mano" si ripercuote sul processo "invocante".
    L'esecuzione di un nuovo processo è una funzione che l'xbox ha di default e si basa su una call EXEC, il problema è che all'esecuzione della EXEC viene fatta una "clean room", ovvero viene cancellata tutta la memoria tranne un area di pochi K (16 mi pare) dove vengono messi i parametri con cui si esegue il nuovo processo e, ovviamente, il BIOS.
    Nota, non essendoci nessuna rilocazione della memoria ne consegue che il BIOS stesso (o per meglio dire l'ESTRATTO del BIOS) è presente in memoria ed è tranquillamente "leggibile".
    Per evitare che qualcuno modificasse tale codice il chipset nVidia prevede una funzione di "lock" che impedisce la scrittura su alcune parti della memoria.
    Ovviamente tale sistema funziona solo se attivato e ovviamente si può disattivare la protezione, il che è quello che fà il loader all'interno di 007 AUF e Mechwarrior, il codice in soggetto si limita a sbloccare un area di 16K dove è contenuta la chiave di validazione degli XBE (cfr. il sito di XBox Linux).
    Sovrascrivendo la chiave con una le cui fattorizzazioni sono note è possibile firmare degli XBE che la XBox riterrà validi.
    Ovviamente la sovrascrittura di questa chiave modifica tutti i CRC (che sono degli hash) del Bios, facendo si che un qualsiasi codice sia in grado di rendersi conto che l'xbox è modificata.

    Se vuoi sapere altro fammi un fischio...
  6. ConteZero

    ConteZero Tribe Member

    Registrato:
    16 Marzo 2005
    Messaggi:
    7.682
    "Mi Piace" ricevuti:
    1
    Punteggio:
    36
    X Zell 1983:
    Mi rendo conto che la cosa non è esattamente facile da leggere e capire ma avendo io studiato questa roba (oltre che ritenerla una cosa divertente di mio) quando qualcuno mi offende dicendo che sto solo scimmiottando cose che non so mi sento punto nel vivo.
    La gente CONVINTA di sapere che, in ultima analisi, basa il suo prestigio sulla pedissequa opera di screditare chiunque gli si possa opporre è la stessa gente che rallenta l'informatica come tutti gli altri ambiti della ricerca e dell'evoluzione umana.
  7. TheHutcher

    TheHutcher <font color=#00FF33><b> Il Miglior Amico di Gogy <

    Registrato:
    16 Dicembre 2002
    Messaggi:
    3.604
    "Mi Piace" ricevuti:
    0
    Punteggio:
    36
    Ah,ah,ah.... questa poi è veramente divertente.... rallentare l'informatica...
    Vabbè, il classico studente.... insisto, quando avrai realizzato qualcosa, qualsiasi cosa per l'Xbox allora può darsi che ascoltarti diventi interessante, nel frattempo, per citare un famoso film mi pare che tu sia "solo chiacchiere e distintivo"....
    Ti lascio, definitivamente (non tornerò a leggere altri tuoi sproloqui) con un quesito:
    Puoi spiegare a tutti in maniere comprensibile come è possibile che quello che chiami BIOS (Kernel per gli altri) stia in 16k di memoria quando, pur essendo compresso, ne occupa oltre 200 su flash (tralasciando loader e compagnia bella...) ?
    Ciao, e auguri per la laurea....
  8. ConteZero

    ConteZero Tribe Member

    Registrato:
    16 Marzo 2005
    Messaggi:
    7.682
    "Mi Piace" ricevuti:
    1
    Punteggio:
    36
    mi cito:
    > Ovviamente tale sistema funziona solo se attivato e ovviamente si può disattivare la protezione, il che è quello che fà il loader all'interno di 007 AUF e Mechwarrior, il codice in soggetto si limita a sbloccare un area di 16K dove è contenuta la chiave di validazione degli XBE (cfr. il sito di XBox Linux).

    [cfr.http://xbox-linux.sourceforge.net/docs/007analysis.html]

    Costruzione grammaticale "ovvero viene cancellata tutta la memoria tranne un area di ...(omissis)... e, ovviamente, il BIOS.
    Dove ho detto che il BIOS è di 16K?

    mi cito:
    > L'esecuzione di un nuovo processo è una funzione che l'xbox ha di default e si basa su una call EXEC, il problema è che all'esecuzione della EXEC viene fatta una "clean room", ovvero viene cancellata tutta la memoria tranne un area di pochi K (16 mi pare) dove vengono messi i parametri con cui si esegue il nuovo processo e, ovviamente, il BIOS.

    Non ho mai detto che il bios fosse di tale dimensione tengo a fare invece notare che la chiave è in un blocco di 16K (e in effetti solo 4 bytes vengono alterati).
    Se vai a controllare le modalità di shadowing delle aree di memoria (che tra parentesi sono bene o male le stesse su tutti i chipset e si utilizzano perchè molti BIOS delle schede ISA in origine venivano copiati nell'area di memoria compresa fra i primi 640K ed il primo mega ti accorgerai che il lock/unlock in scrittura delle aree è diviso in blocchi di 16K allineati con un boundary di 16K.
    Se vai su xboxhacker.net troverai miei post discretamente vecchi e comunque non mi pare che tu (cazzaro convinto) abbia dato un motivo che sia uno per reputarti degno di discutere di queste cose (troll).
    Se poi ho scritto delle cose (e forse le ho scritte) non crederai che mi metta a sbandierarlo ai 4 venti come un cretino.

    Sveglia! non hai dimostrato da nessuna parte dei tuoi post polemici di capire solo uno dei concetti esposti e continui a usare il paravento del "quando vedrò..." per difenderti; a questo punto il tuo problema non sono io è la tua stessa stopposa superiorità da milanese idiota (non ce l'ho con i milanesi ma con gli idioti si), sappi che non sono io a dovermi preoccupare ma tu in quanto chiunque leggerà questo thread capirà chi di noi due tira a fare il cazzaro.

    Tengo infine a dirti che il TSOP contenente il codice "embedded" dell'xbox contiene una miniarea che scompatta un loader ed effettua dei check, questo loader infine estrae un minisistema che rimane in memoria fino al riavvio successivo.
    Segue che nel TSOP è presente un codice di bootup (detto in generale BIOS) ed un miniloader con le funzioni primarie ed un minuscolo Kernel.
    Se, per nostra natura, chiamiamo BIOS il kernel (cosa che non è comunque sbagliata visto che BIOS sta per "Basic Input Output System ed effettivamente è una delle sue funzioni) non vedo la cosa un pretesto per buttare alle ortiche una trattazione che non ha alcuna velleità di essere tecnica ma vuol essere un introduzione.

    Se poi tu sei qui per cavillare sulle virgole vorrei farti notare la frase: (ti cito alla lettera)
    "ci sono diverse occasioni in cui la macchina esegue più thread, lanciati da un unico processo, contemporaneamente e senza terminazione del processo originante".
    Se parli di un processo "originante" vuol dire che ti riferisci a un processo "derivato" o "figlio" ma la tua frase non parla di esecuzione di processi quanto di spawn di thread, vorrei farti notare che un processo monolitico è un processo con un solo thread all'interno, mentre i processi possono avere piu thread all'interno senza che questo "snaturi" o costringa alla terminazione... di che?
    Vatti a fare un corso di terza elementare su uova e galline che mi sà che ne hai bisogno.

    D'ora in poi "Do not feed the troll".
  9. plut0ne

    plut0ne Tribe Newbie

    Registrato:
    10 Giugno 2003
    Messaggi:
    56
    "Mi Piace" ricevuti:
    0
    Punteggio:
    6
    Ehehe W Contezero sapessimo noi tutto quello che sa lui.. :DD