kemi (statz) | #2, Főfasz (2970) |
607 | #2cf0 | ^ | Idézet | Fri, 30 May 2014 06:31:29 +02 |
94.21.*.* | *.pool.digikabel.hu |
Ja. Néha produkál megmagyarázhatatlan jelenségeket. Tegnap adtak nekem egy jó 300 oldalas pdf doksit, hogy tanulmányozzam, természetesen a winfos közben elkezdett visszaszámlálni, hogy ő most frissíteni fog, és zárjak be mindent. Elhalasztani nem lehet, amikor meg lejár a számláló, akkor szó nélkül újraindul, meg se kérdezi, hogy van-e elmenteni valóm, újraindulás után még jó fél órát frissít, mindezt az értékes munkaidőből veszi el, aztán meg kereshetem a doksiban, hogy hol tartottam. Ennél jobb "operációs rendszer" nincs! |
TCH (statz) | #1, Főfasz (10443) |
486 | #2cf1 | ^ | Idézet | Fri, 30 May 2014 09:46:59 +02 |
188.36.*.* | *.catv.pool.telekom.hu |
Hát igen, ez a frissítési mizéria volt az egyik fő oka, hogy nem voltam sosem hajlandó átállni 98-ról xp-re, hanem inkább (9 évvel később) 98-ról már Linuxra váltottam. De egyébként, amikor mégis suxp-t voltam kénytelen használni, akkor én is szívtam vele, viszont némi tekézés (kuglizás) után ráleltem egy sorstársam tippjére, hogy hogy lehet elküldeni véglegesen a picsába ezt a szart:net stop wuauservPersze ez csak addig marad így, amíg nem indítod újra a gépet. |
kemi (statz) | #2, Főfasz (2970) |
1140 | #2cf2 | ^ | Idézet | Sat, 31 May 2014 18:27:59 +02 |
217.197.*.* | *.pool.digikabel.hu |
Processnévre keres, visszaadja az első találat PIDjét, egyébként -1-et.int getPID(QString processName) { #ifdef _WIN32 QProcess proc; proc.start("tasklist"); proc.waitForFinished(); while (!proc.atEnd()) { QString s = proc.readLine(); if (s.startsWith(processName)) { return s.simplified().split(" ")[1].toInt(); } } return -1; #else QProcess proc; QStringList args; args << "-c" << "ps aux | grep \"" + processName + "\" | grep \"root\""; proc.start("/bin/sh", args); proc.waitForFinished(); QString s = proc.readLine(); QStringList list = s.simplified().split(" "); if (list[0] != "root") { return -1; } return list[1].toInt(); #endif } Ha meg olyasmit akarsz kiíratni a couttal, amit nem tud (jelen esetben egy QStringet), akkor egy ilyen függvényt kell írni: ostream& operator<<(ostream& os, QString s) { os << s.toStdString(); return os; } |
TCH (statz) | #1, Főfasz (10443) |
1705 | #2cf3 | ^ | Idézet | Sat, 31 May 2014 20:05:30 +02 |
188.36.*.* | *.catv.pool.telekom.hu |
Hmm kemi, nem biztos, hogy az a legoptimálisabb, ha külső parancsokat hívsz meg rá, mert pl. mi van, ha nincs ps vagy grep (vagy akár tasklist, ha winfos)? Én inkább a /proc mappa túrását javallanám (legalábbis Unix alatt), gyorsabb is (nem kell a háttértárhoz nyúlni többször is), meg biztosabb is.#include <dirent.h> #include <stdio.h> #include <string.h> #include <stdlib.h> long int get_pid_by_process_name(char *pname) { DIR *d; struct dirent *dir; FILE *f; char entry[24]; char buf[256]; long int l; d = opendir("/proc"); if (d) { while ((dir = readdir(d)) != NULL) { strcpy(entry, "/proc/"); strcat(entry, dir->d_name); strcat(entry, "/cmdline"); f = fopen(entry, "rb"); if (f != NULL) { fread(&buf[0], 1, 256, f); fclose(f); l = -1; while ((++l < 257) && (buf[l]) && (buf[l] != 32)); buf[l] -= (buf[l] == 32) << 5; if (l) { while ((buf[--l] != 47) && l); l += (buf[l] == 47); if (!strcmp(pname, &buf[l])) { return atol(dir->d_name); } } } } return -1; /* nincs ilyen */ closedir(d); } return -2; /* nem lehet megnyitni a /proc-ot */ } Ööö...ezt miért kell így? Úgy nem lehet, hogy cout << s.toStdString()? Egyébként ez nem függvény, hanem operator overload. |
kemi (statz) | #2, Főfasz (2970) |
1163 | #2cf4 | ^ | Idézet | Sat, 31 May 2014 20:47:32 +02 |
217.197.*.* | *.pool.digikabel.hu |
Mert így harmadannyi kódból meg lehet oldani. Bár ezt is meg lehet írni tömörebben C++-ban. Így viszont probléma a /proc könyvár elérése (mi van, ha nem rootként fut?) grep, ps, meg tasklist mindig van, hiszen az az oprendszer alaptartozéka. Meg lehetett volna úgy oldani, hogy csak a ps aux kimenetét túrom végig, nem tudom hogy gyorsabb. Winfoson azért folyamodtam ahhoz a megoldáshoz, mert nem lehet összefűzni parancsokat. Hát mert ha mondjuk több stringet akarsz összefűzni, esetleg vegyesen standard meg QString akkor nem kell konvertálgatni. Attól még az függvény, csak implicit hívódik meg. |
Promatheus alias "Prometheus" | #3, Főfasz (1824) |
81 | #2cf5 | ^ | Idézet | Sat, 31 May 2014 20:49:40 +02 |
80.98.*.* | *.catv.broadband.hu |
Ez a függvény implicit, Adjatok inkább cicit! Kemi, hogy állsz a játékunkkal? :) |
TCH (statz) | #1, Főfasz (10443) |
1719 | #2cf6 | ^ | Idézet | Sat, 31 May 2014 22:14:31 +02 |
188.36.*.* | *.catv.pool.telekom.hu |
Cserébe 50x lassabb és függőségei vannak. Olvasáshoz nem kell root jog, ha meg olvasási jog sincs, akkor a te kódod sem fog menni, mert a ps is a /proc mappából olvasgat. A Linux vagy a BSD nem oprendszerek, hanem kernelek. Az a kód, amit én adtam, csak a kernelre támaszkodik. Tök mindegy, mert a külső meghívások miatt sokkal lassabb mindenképpen. Ha nem hiszel nekem, akkor benchmarkold ki, hogy mennyi idő, amíg a tiéd lefut, meg amíg az enyém. Dehogynem, hiszen a te overloadolt operátorod is ugyanazt csinálja: meghívja a konverter metódust, de azt te is csinálhatod: cout << s1.toStdString() << s2.toStdString() << s3.toStdString();
Eszerint nem az. |
TCH (statz) | #1, Főfasz (10443) |
2944 | #2cf7 | ^ | Idézet | Sat, 31 May 2014 22:51:19 +02 |
188.36.*.* | *.catv.pool.telekom.hu |
Kibenchmarkoltam én:/* pidfind_tch */ #include <dirent.h> #include <stdio.h> #include <string.h> #include <stdlib.h> long int get_pid_by_process_name(char *pname) { DIR *d; struct dirent *dir; FILE *f; char entry[24]; char buf[256]; long int l; d = opendir("/proc"); if (d) { while ((dir = readdir(d)) != NULL) { strcpy(entry, "/proc/"); strcat(entry, dir->d_name); strcat(entry, "/cmdline"); f = fopen(entry, "rb"); if (f != NULL) { fread(&buf[0], 1, 256, f); fclose(f); l = -1; while ((++l < 257) && (buf[l]) && (buf[l] != 32)); buf[l] -= (buf[l] == 32) << 5; if (l) { while ((buf[--l] != 47) && l); l += (buf[l] == 47); if (!strcmp(pname, &buf[l])) { return atol(dir->d_name); } } } } return -1; /* nincs ilyen */ closedir(d); } return -2; /* nem lehet megnyitni a /proc-ot */ } int main(int argc, char *argv[]) { /*QCoreApplication a(argc, argv);*/ int i; for (i = 0; i < 1000; ++i) { get_pid_by_process_name("konsole"); get_pid_by_process_name("opera"); get_pid_by_process_name("d3lphin"); get_pid_by_process_name("mousepad"); } return 0; } /* pidfind_kemi */ #include <QCoreApplication> #include <QProcess> #include <QStringList> #include <stdio.h> int getPID(QString processName) { QProcess proc; QStringList args; args << "-c" << "ps aux | grep \"" + processName + "\" | grep \"root\""; proc.start("/bin/sh", args); proc.waitForFinished(); QString s = proc.readLine(); QStringList list = s.simplified().split(" "); if (list[0] != "root") { return -1; } return list[1].toInt(); } int main(int argc, char *argv[]) { /*QCoreApplication a(argc, argv);*/ int i; for (i = 0; i < 1000; ++i) { getPID("konsole"); getPID("opera"); getPID("d3lphin"); getPID("mousepad"); } return 0; }Tessék kemi. Ugyanaz a keret, ugyanúgy Qt5 fordítja, ugyanúgy 4 féle processt keres, ugyanúgy 1000x fut le, minden ugyanaz, csak a tiéd a ps-t és a grep-et hívogatja rendszerhívással, az enyém meg a /proc könyvtárat túrja. Eredmény: root@Csabi:~/qtproj/build-pidfind-Desktop_Qt_5_3_0_GCC_64bit-Debug# time pidfind_tch real 0m1.729s user 0m0.264s sys 0m1.424s root@Csabi:~/qtproj/build-pidfind-Desktop_Qt_5_3_0_GCC_64bit-Debug# time pidfind_kemi real 1m9.365s user 0m23.216s sys 0m29.176sAz enyém 1729 ms alatt végzett, a tiéd 69365 ms alatt. A különbség 40x-es. (Nem is becsültem olyan rosszul, az előző postomban; nagyságrendileg stimmelt.) Komment azt hiszem nem szükséges. Rövidebb kód != gyorsabb kód. |
kemi (statz) | #2, Főfasz (2970) |
1379 | #2cf8 | ^ | Idézet | Sun, 01 Jun 2014 09:54:42 +02 |
217.197.*.* | *.pool.digikabel.hu |
Van erre is "szebb" Qt-s megoldás:int getPID(QString processName) { QDirIterator iterator("/proc"); QString s; QString name; QFile f; while (iterator.hasNext()) { s = iterator.next(); f.setFileName(s + "/comm"); if (f.open(QIODevice::ReadOnly)) { name = f.readLine(); f.close(); if (name.contains(processName)) { return s.split("/")[2].toInt(); } } } return -1; }A tied persze gyorsabb, mert az csak a libc-re támaszkodik. kemi242@linux-93id:~/getpid/bin> time ./getpid_ps real 1m21.628s user 0m29.981s sys 0m50.390s kemi242@linux-93id:~/getpid/bin> time ./getpid_qt real 0m13.016s user 0m5.858s sys 0m7.153s kemi242@linux-93id:~/getpid/bin> time ./getpid_tch real 0m2.815s user 0m0.354s sys 0m2.459s Lehet úgy is, de ha van operátor kevesebbet kell gépelni, olvashatóbb a kód, ha meg elérod az inline kulcsszót ugyanerre fordul, vagyis semmivel nem lesz lassabb. |
TCH (statz) | #1, Főfasz (10443) |
3931 | #2cf9 | ^ | Idézet | Sun, 01 Jun 2014 10:41:12 +02 |
188.36.*.* | *.catv.pool.telekom.hu |
Az enyém nem azért gyorsabb, mert csak a libc-re támaszkodik, hanem azért, mert te objektumosan dolgozod fel és annak ekkora overheadje lesz. A másik viszont nem meglepő, hogy ennyivel lassabb, mind a kettőnél. Gondold végig, az enyém egyszer végigmegy magán a processlisten, olvasgatja a neveket és ha megtalálja amit keresett, akkor kiszáll. A tiéd meghívja a ps-t, ami végigmegy a teljes processlisten, kiolvassa az összes nevet és be is küldi őket a csőbe! Utána még két grep hívás is lesz, amiknek nem egy-egy sort kell parse-álniuk, hanem egy egész listát! És ez is csöveken keresztül megy, ami csak tovább lassítja a dolgot. És akkor azt még nem is kalkuláltuk bele, hogy négyszer is futtatható állományokat kell elindítani (sh, ps, grep, grep). Σ: Háttértárhoz való nyúlkálás és processzek közti full-text kommunikáció, csöveken. Ergo ez a módszer nagyságrendekkel lassabb lesz, mint egy közvetlenül a memóriából olvasgató for-ciklus. Azt viszont nem is tudtam, hogy a comm-ba csak a process name van, mindenütt a cmdline-t írták, azt meg parse-lni kell. Így ki lehet egyszerűsíteni az én kódomat is: #include <dirent.h> #include <stdio.h> #include <string.h> #include <stdlib.h> long int get_pid_by_process_name(char *pname) { DIR *d; struct dirent *dir; FILE *f; char entry[24]; char buf[256]; size_t l; d = opendir("/proc"); if (d) { while ((dir = readdir(d)) != NULL) { strcpy(entry, "/proc/"); strcat(entry, dir->d_name); strcat(entry, "/comm"); f = fopen(entry, "rb"); if (f != NULL) { l = fread(&buf[0], 1, 256, f); fclose(f); buf[l-1] = 0; /* az utolso byte mindig egy LF! */ if (!strcmp(pname, &buf[0])) { return atol(dir->d_name); } } } return -1; /* nincs ilyen */ closedir(d); } return -2; /* nem lehet megnyitni a /proc-ot */ } root@Csabi:~/qtproj/build-pidtest-Desktop_Qt_5_3_0_GCC_64bit-Debug# time pidfind_tch real 0m1.710s user 0m0.264s sys 0m1.404s root@Csabi:~/qtproj/build-pidtest-Desktop_Qt_5_3_0_GCC_64bit-Debug# time pidfind_tch2 real 0m1.785s user 0m0.280s sys 0m1.468sViszont az a vicc, hogy ez a lassabb bazmeg (~4.5%-al)! Valószínűleg a comm elérése lassabb, mint a cmdline-é. Van rá egy gazdaságos huszasom, hogy azért, mert a cmdline az simán visszaadja azt a memóriaterületet, ahol az adott process indítási parancssora van, míg a comm az kiparse-álja belőle helyettem a processnevet. Ezek szerint sikerült erre a célra gyorsabb parsert írnom, mint ami a Linux kernelben van. :P (Nyilván azért, mert az enyém csak a processnevet keresi meg benne, mással nem foglalkozik.) Hmm és ráadásul le is van limitálva! Vagyis a comm csak azokat a processneveket adja vissza rendesen, amik rövidebbek, mint 16 byte (mert ugye az utolsó byte mindig egy LF). Nagyon jó... Teszt: root@Csabi:~# cat /proc/3218/comm vmware-authdlau root@Csabi:~# cat /proc/3218/cmdline /usr/sbin/vmware-authdlauncherIgen. Vagyis a comm konkéltan használhatatlan, a normális megoldás a cmdline parsingja. |
kemi (statz) | #2, Főfasz (2970) |
253 | #2cfa | ^ | Idézet | Sun, 01 Jun 2014 15:42:54 +02 |
217.197.*.* | *.pool.digikabel.hu |
Winfoson is biztos van hatékonyabb megoldás, hiszen a tasklistet is megírták valahogy, csak nem ilyen egyszerű, meg nincs forráskód. A winapi doksijába kéne beleolvasni (vagy le van szarva az egész, winfoson lassú lesz :P). Nem baj, azért kösz a tippet. |
TCH (statz) | #1, Főfasz (10443) |
2061 | #2cfb | ^ | Idézet | Sun, 01 Jun 2014 16:41:05 +02 |
188.36.*.* | *.catv.pool.telekom.hu |
Nincs mit. Közben beleraktam még egy két dolgot (pl. nagyobb chartömböket, mert a terminator is a string része és az fread kimenetének vizsgálását is, hogy ha nincs NUL a végén, akkor se folytassa a buf olvasását, mert akkor rámehet olyan adatokra, amik az előző körből maradtak ott), átszerveztem a kiszálló ágakat, hogy átláthatóbb legyen és megcsináltam visszafelé is, azaz processnév kiolvasása pid alapján. Ehun gp.c:#ifndef _GP_C #define _GP_C 1 #include <dirent.h> #include <stdio.h> #include <string.h> #include <stdlib.h> char *get_process_name_by_pid(long int pid) { FILE *f; char spid[11]; char entry[25]; char buf[256]; long int l, c; char *result; sprintf(spid, "%d", pid); strcpy(entry, "/proc/"); strcat(entry, spid); strcat(entry, "/cmdline"); f = fopen(entry, "rb"); if (f == NULL) { return NULL; } c = fread(&buf[0], 1, 256, f); fclose(f); l = -1; while ((++l < 257) && (l < c) && (buf[l]) && (buf[l] != 32)); buf[l] -= (buf[l] == 32) << 5; if (!l) { return NULL; } while ((buf[--l] != 47) && l); l += (buf[l] == 47); result = malloc(strlen(&buf[l])); if (result != NULL) { strcpy(result, &buf[l]); } return result; } long int get_pid_by_process_name(char *pname) { DIR *d; struct dirent *dir; FILE *f; char entry[25]; char buf[256]; long int l, c; d = opendir("/proc"); if (!d) { return -2; } while ((dir = readdir(d)) != NULL) { strcpy(entry, "/proc/"); strcat(entry, dir->d_name); strcat(entry, "/cmdline"); f = fopen(entry, "rb"); if (f != NULL) { c = fread(&buf[0], 1, 256, f); fclose(f); l = -1; while ((++l < 257) && (l < c) && (buf[l]) && (buf[l] != 32)); buf[l] -= (buf[l] == 32) << 5; if (l) { while ((buf[--l] != 47) && l); l += (buf[l] == 47); if (!strcmp(pname, &buf[l])) { return atol(dir->d_name); } } } } closedir(d); return -1; } #endif |
kemi (statz) | #2, Főfasz (2970) |
749 | #2cfc | ^ | Idézet | Sun, 01 Jun 2014 17:13:57 +02 |
217.197.*.* | *.pool.digikabel.hu |
Winfoson így néz ki:#include <windows.h> #include <tlhelp32.h> int getPID(wchar_t* name) { PROCESSENTRY32 entry; entry.dwSize = sizeof(PROCESSENTRY32); HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); if (Process32First(snapshot, &entry) == TRUE) { while (Process32Next(snapshot, &entry) == TRUE) { if (wcscmp(entry.szExeFile, name) == 0) { HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); DWORD processId = GetProcessId(hProcess); CloseHandle(hProcess); return processId; } } } CloseHandle(snapshot); return -1; } |
TCH (statz) | #1, Főfasz (10443) |
26 | #2cfd | ^ | Idézet | Sun, 01 Jun 2014 18:10:42 +02 |
188.36.*.* | *.catv.pool.telekom.hu |
Úristen... WinAPI sucks... |
kemi (statz) | #2, Főfasz (2970) |
288 | #2cfe | ^ | Idézet | Sun, 01 Jun 2014 20:20:19 +02 |
217.197.*.* | *.pool.digikabel.hu |
Kilométer hosszú függvénynevek még hagyján, de teljesen felrúgja a C++-os konvenciót: Qt-n, és mindenhol máshol az osztály és konstruktornevek nagybetűvel, a többi kisbetűvel kezdődik, a winapiban meg vegyesen van minden. |
TCH (statz) | #1, Főfasz (10443) |
373 | #2cff | ^ | Idézet | Sun, 01 Jun 2014 20:30:05 +02 |
188.36.*.* | *.catv.pool.telekom.hu |
Én nem a kód kinézetéről beszéltem kemi, azt én magasról leszarom. (Jó, ezek a borzasztó hosszú függvénynevek engem is idegesítenek, ezeken annyira látszik, hogy a retardáltaknak nevezték el így...) Én arról beszélek, hogy maga az API fos. Könyörgöm, ki kell nyitni a process-t magát, hogy megtudjam az azonosítóját?! Nincs egy process table az OS-ben amit le lehet kérni?! |