Többszálú programokkal kapcsolatos kérdések helye.
Hozzászólások
Nincs-e valaki olyan helyzetben, hogy többprocesszoros gépen tudná futtatni a tesztprogramokat? Amikor nekem hozzáférésem volt ilyenhez, akkor még nem volt benne a CCC-ben a többszálúság, most meg csak egyprocesszoros gépeim vannak.
Fogalmam sincs, mi a különbség. De ezeket külön tesztelni kell, mert az ember sohase tudhatja. A többprocesszoros esetről sincs semmi előzetes elképzelésem.
Akkor mondd, hogyan kell tesztelni. Én ezek szerint viszonylag régóta használom kétmagos gépen a CCC-t, még sose volt belőle gondom. De mondd, mit indítsak. Pi-számoló?
Azokat is amik az x-crash-ben vannak. Itt olyan programok vannak, amik bizonyos (már kijavított) hibák megléte esetén viszonlyag rövid úton elrontják a futtatórendszert. Az x-array0.prg pedig demonstrál egy kijavíthatatlan hibát.
A CCC2-ből a ccctutor/signal-ban levő programokat. Ezek gyötrő programok, amik rengeteg szálon mindenfélét csinálnak, miközben szignálokat is kezelnek. Hogy legyen külső forrásból származó szignál CTRL-C nyomó szerkezetet szoktam használni hozzá (amiért a gyerekeim kiröhögnek).
Kérünk fényképet a Ctrl-C nyomó szerkezetről, mi is szeretnénk röhögni :D
Windowsos teszteredmények:
array-test.exe: másfél procit eszik, tehát 75%-ra járatja a kétmagos gépet, baja nincs. Át kellett írni a bedrótozott könyvtárnevet. A prociból valszleg a random sleep miatt eszik ilyen ugrálóan.
clid_ext.exe: nem hátalt el, annak megfelelően viselkedik, ahogy le van írva benne.
pi.exe: működik.
threads.exe: szépen futik, praktikusan nem eszik procit, 5% körül, a 0.05 miatt az inkey-ben.
x-crash-ban nincs m.bat.
x-array0: el nem hátalt, sok más jele nincs a működésének.
x-valueassign: nekem jól ment, hagytam elmenni 320-ig, aztán meguntam, nem bír hibázni.
Az x-array0-nak idővel el kell szállnia. Ez a kritikus dolog:
array(1)[1]:=1
Az array függvény csinál egy array-t, amire azonban egyetlen változó sem hivatkozik, ezért a szemétgyűjtés letakaríthatja. Ugyanakkor ennek a tömbnek az első elemébe beírjuk az 1-t. A program ezt az egy utasítást ismételgeti, miközben egy másik szál folyamatosan indítgatja a szemétgyűjtést. Előbb-utóbb el kell szállnia. Az a szerencse, hogy a dolog értelmetlen. Mihelyt értelmet adunk neki, nem is akar elszállni, ez pl. jó:
(x:=array(1))[1]:=1
mert itt az x változó hivatkozik az array-re, tehát nem lesz letakarítva.
A signal-os crash programokat majd átrakom CCC3-ba.
Hogy érzékeltessem a tesztelés nehézségeit leírom, hogy megy a dolog. Veszek egy gyötrő programot, rengeteg szálon véletlenszerű időzítéssel mindenfélét csinál, plusz folyamatosan CTRL-C-t és egyéb szignálokat kezel, miközben folyamatosan gyűjti a szemetet. Hagyom futni egy-két napig. Ha nem száll el, áttérek más gyötrő programra.
Utoljára 2 éve foglalkoztam ezzel, és úgy hagytam abba a tesztelést, hogy nem volt kijavítatlan hiba (kivéve az x-array0 esetet).
Ha hiba van (tipikusan SIGSEGV, deadlock), akkor a direkt debug célra átállított szignál kezelő SIGSTOP-pal megállítja a programot, a gdb-vel pedig meg lehet nézni, hogy hol következett be a leállás. Ilyen próbálgatással lassanként kialakul az érzés, hogy hol vannak kényes pontok, és akkor a gyötrő programot lehet úgy kissebbíteni, hogy jobban a kényes pontra fókuszáljon, miáltal a lefagyásoknak sűrűsödnie kell. Ha már kellően sűrűek a lefagyások, akkor meg is lehet találni a hibát. Volt olyan hiba, amivel több héten át küzdöttem, amíg sikerült úgy besűríteni az előfordulását, hogy ki lehessen javítani.
Igen, valóban elszállogat Windowson. Ámde most Linuxon tesztelek, és az az érdekesség van, hogy itt gyakorlatilag csak 1 procit eszik meg az x-array0.
array-test.exe szintén.
threads.exe összesen nem eszik meg 10%-ot a két magból. Ha nem nézem a konzolt, amin borul a matéria, akkor ötöt se.
A többi program is hasonlóan viselkedik, amúgy nincs velük gond. Érdekes módon x-array0-t se tudtam elszállítani 4 óra alatt, itthagyom majd éjszakára. Viszont azt kitartóan nem értem, hogy miért nem használják ki a több magot. Én konfiguráltam volna félre valamit?
Mi szállogat el? Az x-array0-nak el _kell_ szállnia (előbb-utóbb), a többinek elvileg nem szabadna.
"Viszont azt kitartóan nem értem, hogy miért nem használják ki a több magot."
Tudjuk-e biztosan, hogy a többmagos processzor==több processzor? Én nem tudom. Azt se tudom, hogy többprocesszoros gépen mindig magától kihasználódik-e minden CPU.
Egyprocesszoros gépen az a helyzet, hogy a tesztelési célokhoz képest túl ritkán vált az ütemező a különböző szálak között (Solarison különösen ritkán). Ezért van a programokban itt-ott egy-egy sleep(1), mert abból rájön az ütemező, hogy váltani lehet. Emiatt a CPU kihasználtság nem maximális. A sleepekkel talán érdemes kísérletezni.
A threads.exe esetében a teszt célja csak annyi, hogy nem fogynak-e el a threadid-k. Detach és join nélkül elfogynának. Azonkívül az is látszik, hogy 64 bites rendszeren a threadid-k 64 bitesek, tehát csak P típusú változóban lehet őket tárolni.
Igen, az x-array0 szállogat el, a többi nem.
Azt tudom biztosan a többmagos processzorról, hogy mind a Linux kernel, mind a Windows XP kernele többprocesszorosnak ismeri fel, és a terhelés szempontjából is így viselkedik, tehát ha mondjuk egy egyszálú alkalmazás beakad, és százra eszi a procit bármi okból, akkor észre sem veszem, ha nincs fenn valami prociterhelés-figyelő, mert a gép egy fikarcnyit sem lassul tőle. Tehát szerintem bátran tekinthetjük annak, főleg, hogy ha jól tudom, akkor gyártástechnológiailag is arról van szó, hogy két processzormagot begyömöszöltek egy tokba.
Majd kísérletezem a sleep-ekkel kicsit később.
Leírom pár sorban, mivel szerencsétlenkedtem a napokban.
Elővettem egy korábbi nyúzó (crash) programot, ami a következőket csinálja: Elindít sok szálat (egyszerre 10-15 fut, újak keletkeznek, régebbiek kilépnek), ezek folyamatosan mindenféle string-, array-, objektumműveleteket csinálnak. Egy szál állandóan gyűjti a szemetet, egy szál szignálokat küld a programnak, egy másik (külső) program szintén folyamatosan szignálokat küld, időnként én is nyomkodom neki a CTRL-C-t. A program kezeli a szignálokat, a szignálkezelő szintén string-, array-, objektumműveleteket végez.
Az egésznek az a célja, hogy a változókezelés/szemétgyűjtés hibáit felderítse. Ilyen hibát már évek óta nem találok, vannak viszont deadlockok. Deadlock úgy lehet, hogy a szignálkezelő fennakad egy olyan mutexen, amit ugyanez a szál még a szignál előtt lockolt, hogy elkerülje az összeakadást más szálakkal (Megj: "fast" mutexeket használok, amit ugyanaz a szál sem tud egynél többször lockolni.) Csakhogy a CCC védekezik az ilyen deadlockok ellen: amíg lockolva tart egy mutexet, addig blockolja a szignálokat. Az ilyen szignálok nem vesznek el, csak a mutex lock feloldása után jutnak érvényre. Nem kéne tehát, hogy deadlockok legyenek, mégis vannak, persze nem gyakran, félóránként sikerül egyet-egyet előidézni.
Nekiálltam tehát felderíteni, mi okozza a deadlockokat. Csináltam egy olyan mutex lock/unlock wrappert, ami saját nyilvántartást vezet a mutex lockokról, és deadlock esetén úgy áll meg, hogy a gdb backtrace paranccsal meg lehessen nézni, hogy mi akadt össze. Az eredmény: a libc-beli malloc-ban és free-ben van olyan mutex lock/unlock pár, ami nincs védve a szignálok ellen. Mondjuk a free éppen lockolva tartja a mutexet, amikor szignált kap és elmegy szignált kezelni. A szignálkezelő objektumműveleteket végez, de ehhez meg kell várnia, hogy a másik szálon futó szemétgyűjtés lefusson. Csakhogy a szemétgyűjtés nem tud befejeződni, mert fennakad a free-ben lockolva tartott mutexen.
Nekiálltam tanulmányozni a malloc_hook témát. Látszólag könnyű csinálni olyan hookot, ami végrehajtja az eredeti malloc implementációt, de eközben blockolja a szignálokat. Valóban, ilyen hookokkal a nyúzó órákon keresztül sem tudott deadlockot előidézni. Persze ez nem jelenti azt, hogy a deadlock probléma meg volna oldva, hiszen védtelen mutexek más rendszerhívásokban is lehetnek. Nem is az a cél. A cél a CCC épségének ellenőrzése, a hook csak kiiktat egy ellenőrzést zavaró tényezőt.
Gondoltam, ha már vannak ilyen hookjaim, akkor megszámolom a memóriablokkokat, ezzel ugyanis lehet ellenőrizni, hogy nincs-e memóriaszivárgás. Csináltam egy saját nyilvántartást a memóriablokkokról. A következő "hibákra" derült fény:
Vannak nem lefoglalt, de felszabadított blokkok.
Vannak többször felszabadított blokkok.
Vannak nem felszabadított blokkok, aminek a címét a malloc újra kiadja.
Rögtön megjegyzem, hogy nem a CCC, hanem a nyilvántartás rossz. A hibák úgy keletkeznek, hogy a malloc/free/realloc néha kikerüli a hookot. Egyszálú esetben a hookok 100%-osan működnek, a nyúzóban viszont kb. az esetek 1%-ában a hook nem jut érvényre. Utánanéztem a problémának a gugliban. Egy novelles címről valaki rákérdezett ugyanerre, egy redhates címről azt a választ kapta, hogy a malloc_hook-ot felejtse el, nem jó, nem is lehet megjavítani, és úgyis ki fog kerülni a libc-ből.
Kicseréltem tehát a hookolást LD_PRELOAD-dal felszedett wrapperekre. Ez sokkal jobban működik, mint a hook, de (sokkal kisebb számban ugyan) most is vannak olyan free hívások, amikhez nem tartozik (a wrapper által nyilvántartott) malloc. A hibák most is csak többszálú programban jelentkeznek, ezekben is csak akkor, ha sok új szál keletkezik és szűnik meg. Gyanúm szerint magában a pthread_create-ban lehet olyan malloc, aminek valahogy sikerül kikerülnie a wrappert.
A tanulság:
1) Többszálú programokban nincs jó megoldás (vagy csak én nem ismerem) a malloc/free/realloc hookolására. Tehát ilyen technikára nem lehet pl. szemétgyűjtést alapozni. Szerencsére a CCC nem így működik.
2) A CCC szignálkezelés nem biztonságos. Csak a szerencsén múlik, hogy a szignálkezelő nem akad-e el deadlockban. Gyanítom, hogy a Pythonban ugyanez a helyzet. Persze a gyakorlatban ez nagyon ritkán okoz problémát. A z editor pl. SIGHUP-ra történő kilépés előtt elmenti az editált szöveget, és még soha senki nem észlelt eközben deadlockot.
3) A szignálokra egyedüli 100%-osan biztos reakció csak a teljes ignorálás. A kontrollált kilépés már nem annyira biztos, mert a kilépés folyamata közben bármi előfordulhat.
Egy kérdésem lenne. Érdemes linuxnak kétmagos gépet venni? Képesek-e már a programok a többszálas futásra? Ha igen, akkor minden disztró tárolójába belerakták-e, vagy manuálisan kell? Elsősorban a konvertáló/rippelő programokra gondolok.
Hozzászólások
Nincs-e valaki olyan helyzetben, hogy többprocesszoros gépen tudná futtatni a tesztprogramokat? Amikor nekem hozzáférésem volt ilyenhez, akkor még nem volt benne a CCC-ben a többszálúság, most meg csak egyprocesszoros gépeim vannak.
--
CCC3
Kétmagos processzor ér? Mert a laptopom is olyan, meg a munkahelyi gépem is.
w
Fogalmam sincs, mi a különbség. De ezeket külön tesztelni kell, mert az ember sohase tudhatja. A többprocesszoros esetről sincs semmi előzetes elképzelésem.
--
CCC3
Akkor mondd, hogyan kell tesztelni. Én ezek szerint viszonylag régóta használom kétmagos gépen a CCC-t, még sose volt belőle gondom. De mondd, mit indítsak. Pi-számoló?
w
A tutor/multithread-ben az összes programot.
Azokat is amik az x-crash-ben vannak. Itt olyan programok vannak, amik bizonyos (már kijavított) hibák megléte esetén viszonlyag rövid úton elrontják a futtatórendszert. Az x-array0.prg pedig demonstrál egy kijavíthatatlan hibát.
A CCC2-ből a ccctutor/signal-ban levő programokat. Ezek gyötrő programok, amik rengeteg szálon mindenfélét csinálnak, miközben szignálokat is kezelnek. Hogy legyen külső forrásból származó szignál CTRL-C nyomó szerkezetet szoktam használni hozzá (amiért a gyerekeim kiröhögnek).
--
CCC3
Kérünk fényképet a Ctrl-C nyomó szerkezetről, mi is szeretnénk röhögni :D
Windowsos teszteredmények:
array-test.exe: másfél procit eszik, tehát 75%-ra járatja a kétmagos gépet, baja nincs. Át kellett írni a bedrótozott könyvtárnevet. A prociból valszleg a random sleep miatt eszik ilyen ugrálóan.
clid_ext.exe: nem hátalt el, annak megfelelően viselkedik, ahogy le van írva benne.
pi.exe: működik.
threads.exe: szépen futik, praktikusan nem eszik procit, 5% körül, a 0.05 miatt az inkey-ben.
x-crash-ban nincs m.bat.
x-array0: el nem hátalt, sok más jele nincs a működésének.
x-valueassign: nekem jól ment, hagytam elmenni 320-ig, aztán meguntam, nem bír hibázni.
x-valuesort: pont mint valueassign.
CCC2-m nincs, nem is áll szándékomban felrakni.
w
Az x-array0-nak idővel el kell szállnia. Ez a kritikus dolog:
array(1)[1]:=1
Az array függvény csinál egy array-t, amire azonban egyetlen változó sem hivatkozik, ezért a szemétgyűjtés letakaríthatja. Ugyanakkor ennek a tömbnek az első elemébe beírjuk az 1-t. A program ezt az egy utasítást ismételgeti, miközben egy másik szál folyamatosan indítgatja a szemétgyűjtést. Előbb-utóbb el kell szállnia. Az a szerencse, hogy a dolog értelmetlen. Mihelyt értelmet adunk neki, nem is akar elszállni, ez pl. jó:
(x:=array(1))[1]:=1
mert itt az x változó hivatkozik az array-re, tehát nem lesz letakarítva.
A signal-os crash programokat majd átrakom CCC3-ba.
Hogy érzékeltessem a tesztelés nehézségeit leírom, hogy megy a dolog. Veszek egy gyötrő programot, rengeteg szálon véletlenszerű időzítéssel mindenfélét csinál, plusz folyamatosan CTRL-C-t és egyéb szignálokat kezel, miközben folyamatosan gyűjti a szemetet. Hagyom futni egy-két napig. Ha nem száll el, áttérek más gyötrő programra.
Utoljára 2 éve foglalkoztam ezzel, és úgy hagytam abba a tesztelést, hogy nem volt kijavítatlan hiba (kivéve az x-array0 esetet).
Ha hiba van (tipikusan SIGSEGV, deadlock), akkor a direkt debug célra átállított szignál kezelő SIGSTOP-pal megállítja a programot, a gdb-vel pedig meg lehet nézni, hogy hol következett be a leállás. Ilyen próbálgatással lassanként kialakul az érzés, hogy hol vannak kényes pontok, és akkor a gyötrő programot lehet úgy kissebbíteni, hogy jobban a kényes pontra fókuszáljon, miáltal a lefagyásoknak sűrűsödnie kell. Ha már kellően sűrűek a lefagyások, akkor meg is lehet találni a hibát. Volt olyan hiba, amivel több héten át küzdöttem, amíg sikerült úgy besűríteni az előfordulását, hogy ki lehessen javítani.
--
CCC3
igen
Igen, valóban elszállogat Windowson. Ámde most Linuxon tesztelek, és az az érdekesség van, hogy itt gyakorlatilag csak 1 procit eszik meg az x-array0.
array-test.exe szintén.
threads.exe összesen nem eszik meg 10%-ot a két magból. Ha nem nézem a konzolt, amin borul a matéria, akkor ötöt se.
A többi program is hasonlóan viselkedik, amúgy nincs velük gond. Érdekes módon x-array0-t se tudtam elszállítani 4 óra alatt, itthagyom majd éjszakára. Viszont azt kitartóan nem értem, hogy miért nem használják ki a több magot. Én konfiguráltam volna félre valamit?
w
Mi szállogat el? Az x-array0-nak el _kell_ szállnia (előbb-utóbb), a többinek elvileg nem szabadna.
"Viszont azt kitartóan nem értem, hogy miért nem használják ki a több magot."
Tudjuk-e biztosan, hogy a többmagos processzor==több processzor? Én nem tudom. Azt se tudom, hogy többprocesszoros gépen mindig magától kihasználódik-e minden CPU.
Egyprocesszoros gépen az a helyzet, hogy a tesztelési célokhoz képest túl ritkán vált az ütemező a különböző szálak között (Solarison különösen ritkán). Ezért van a programokban itt-ott egy-egy sleep(1), mert abból rájön az ütemező, hogy váltani lehet. Emiatt a CPU kihasználtság nem maximális. A sleepekkel talán érdemes kísérletezni.
A threads.exe esetében a teszt célja csak annyi, hogy nem fogynak-e el a threadid-k. Detach és join nélkül elfogynának. Azonkívül az is látszik, hogy 64 bites rendszeren a threadid-k 64 bitesek, tehát csak P típusú változóban lehet őket tárolni.
--
CCC3
Igen, az x-array0 szállogat el, a többi nem.
Azt tudom biztosan a többmagos processzorról, hogy mind a Linux kernel, mind a Windows XP kernele többprocesszorosnak ismeri fel, és a terhelés szempontjából is így viselkedik, tehát ha mondjuk egy egyszálú alkalmazás beakad, és százra eszi a procit bármi okból, akkor észre sem veszem, ha nincs fenn valami prociterhelés-figyelő, mert a gép egy fikarcnyit sem lassul tőle. Tehát szerintem bátran tekinthetjük annak, főleg, hogy ha jól tudom, akkor gyártástechnológiailag is arról van szó, hogy két processzormagot begyömöszöltek egy tokba.
Majd kísérletezem a sleep-ekkel kicsit később.
w
Leírom pár sorban, mivel szerencsétlenkedtem a napokban.
Elővettem egy korábbi nyúzó (crash) programot, ami a következőket csinálja: Elindít sok szálat (egyszerre 10-15 fut, újak keletkeznek, régebbiek kilépnek), ezek folyamatosan mindenféle string-, array-, objektumműveleteket csinálnak. Egy szál állandóan gyűjti a szemetet, egy szál szignálokat küld a programnak, egy másik (külső) program szintén folyamatosan szignálokat küld, időnként én is nyomkodom neki a CTRL-C-t. A program kezeli a szignálokat, a szignálkezelő szintén string-, array-, objektumműveleteket végez.
Az egésznek az a célja, hogy a változókezelés/szemétgyűjtés hibáit felderítse. Ilyen hibát már évek óta nem találok, vannak viszont deadlockok. Deadlock úgy lehet, hogy a szignálkezelő fennakad egy olyan mutexen, amit ugyanez a szál még a szignál előtt lockolt, hogy elkerülje az összeakadást más szálakkal (Megj: "fast" mutexeket használok, amit ugyanaz a szál sem tud egynél többször lockolni.) Csakhogy a CCC védekezik az ilyen deadlockok ellen: amíg lockolva tart egy mutexet, addig blockolja a szignálokat. Az ilyen szignálok nem vesznek el, csak a mutex lock feloldása után jutnak érvényre. Nem kéne tehát, hogy deadlockok legyenek, mégis vannak, persze nem gyakran, félóránként sikerül egyet-egyet előidézni.
Nekiálltam tehát felderíteni, mi okozza a deadlockokat. Csináltam egy olyan mutex lock/unlock wrappert, ami saját nyilvántartást vezet a mutex lockokról, és deadlock esetén úgy áll meg, hogy a gdb backtrace paranccsal meg lehessen nézni, hogy mi akadt össze. Az eredmény: a libc-beli malloc-ban és free-ben van olyan mutex lock/unlock pár, ami nincs védve a szignálok ellen. Mondjuk a free éppen lockolva tartja a mutexet, amikor szignált kap és elmegy szignált kezelni. A szignálkezelő objektumműveleteket végez, de ehhez meg kell várnia, hogy a másik szálon futó szemétgyűjtés lefusson. Csakhogy a szemétgyűjtés nem tud befejeződni, mert fennakad a free-ben lockolva tartott mutexen.
Nekiálltam tanulmányozni a malloc_hook témát. Látszólag könnyű csinálni olyan hookot, ami végrehajtja az eredeti malloc implementációt, de eközben blockolja a szignálokat. Valóban, ilyen hookokkal a nyúzó órákon keresztül sem tudott deadlockot előidézni. Persze ez nem jelenti azt, hogy a deadlock probléma meg volna oldva, hiszen védtelen mutexek más rendszerhívásokban is lehetnek. Nem is az a cél. A cél a CCC épségének ellenőrzése, a hook csak kiiktat egy ellenőrzést zavaró tényezőt.
Gondoltam, ha már vannak ilyen hookjaim, akkor megszámolom a memóriablokkokat, ezzel ugyanis lehet ellenőrizni, hogy nincs-e memóriaszivárgás. Csináltam egy saját nyilvántartást a memóriablokkokról. A következő "hibákra" derült fény:
Vannak nem lefoglalt, de felszabadított blokkok.
Vannak többször felszabadított blokkok.
Vannak nem felszabadított blokkok, aminek a címét a malloc újra kiadja.
Rögtön megjegyzem, hogy nem a CCC, hanem a nyilvántartás rossz. A hibák úgy keletkeznek, hogy a malloc/free/realloc néha kikerüli a hookot. Egyszálú esetben a hookok 100%-osan működnek, a nyúzóban viszont kb. az esetek 1%-ában a hook nem jut érvényre. Utánanéztem a problémának a gugliban. Egy novelles címről valaki rákérdezett ugyanerre, egy redhates címről azt a választ kapta, hogy a malloc_hook-ot felejtse el, nem jó, nem is lehet megjavítani, és úgyis ki fog kerülni a libc-ből.
Kicseréltem tehát a hookolást LD_PRELOAD-dal felszedett wrapperekre. Ez sokkal jobban működik, mint a hook, de (sokkal kisebb számban ugyan) most is vannak olyan free hívások, amikhez nem tartozik (a wrapper által nyilvántartott) malloc. A hibák most is csak többszálú programban jelentkeznek, ezekben is csak akkor, ha sok új szál keletkezik és szűnik meg. Gyanúm szerint magában a pthread_create-ban lehet olyan malloc, aminek valahogy sikerül kikerülnie a wrappert.
A tanulság:
1) Többszálú programokban nincs jó megoldás (vagy csak én nem ismerem) a malloc/free/realloc hookolására. Tehát ilyen technikára nem lehet pl. szemétgyűjtést alapozni. Szerencsére a CCC nem így működik.
2) A CCC szignálkezelés nem biztonságos. Csak a szerencsén múlik, hogy a szignálkezelő nem akad-e el deadlockban. Gyanítom, hogy a Pythonban ugyanez a helyzet. Persze a gyakorlatban ez nagyon ritkán okoz problémát. A z editor pl. SIGHUP-ra történő kilépés előtt elmenti az editált szöveget, és még soha senki nem észlelt eközben deadlockot.
3) A szignálokra egyedüli 100%-osan biztos reakció csak a teljes ignorálás. A kontrollált kilépés már nem annyira biztos, mert a kilépés folyamata közben bármi előfordulhat.
--
CCC3
Egy kérdésem lenne. Érdemes linuxnak kétmagos gépet venni? Képesek-e már a programok a többszálas futásra? Ha igen, akkor minden disztró tárolójába belerakták-e, vagy manuálisan kell? Elsősorban a konvertáló/rippelő programokra gondolok.
A válasz egyszerű: Érdemes.
--
CCC3