Všem čtenářkám a čtenářům AbcLinuxu krásné Vánoce.
Byla vydána nová verze 7.0 linuxové distribuce Parrot OS (Wikipedie). S kódovým názvem Echo. Jedná se o linuxovou distribuci založenou na Debianu a zaměřenou na penetrační testování, digitální forenzní analýzu, reverzní inženýrství, hacking, anonymitu nebo kryptografii. Přehled novinek v příspěvku na blogu.
Vývojáři postmarketOS vydali verzi 25.12 tohoto před osmi lety představeného operačního systému pro chytré telefony vycházejícího z optimalizovaného a nakonfigurovaného Alpine Linuxu s vlastními balíčky. Přehled novinek v příspěvku na blogu. Na výběr jsou 4 uživatelská rozhraní: GNOME Shell on Mobile, KDE Plasma Mobile, Phosh a Sxmo.
Byla vydána nová verze 0.41.0 multimediálního přehrávače mpv (Wikipedie) vycházejícího z přehrávačů MPlayer a mplayer2. Přehled novinek, změn a oprav na GitHubu. Požadován je FFmpeg 6.1 nebo novější a také libplacebo 6.338.2 nebo novější.
Byla vydána nová verze 5.5 (novinky) skriptovacího jazyka Lua (Wikipedie). Po pěti a půl letech od vydání verze 5.4.
Byla vydána nová verze 5.4.0 programu na úpravu digitálních fotografií darktable (Wikipedie). Z novinek lze vypíchnout vylepšenou podporu Waylandu. Nejnovější darktable by měl na Waylandu fungovat stejně dobře jako na X11.
Byla vydána beta verze Linux Mintu 22.3 s kódovým jménem Zena. Podrobnosti v přehledu novinek a poznámkách k vydání. Vypíchnout lze, že nástroj Systémová hlášení (System Reports) získal mnoho nových funkcí a byl přejmenován na Informace o systému (System Information). Linux Mint 22.3 bude podporován do roku 2029.
GNU Project Debugger aneb GDB byl vydán ve verzi 17.1. Podrobný přehled novinek v souboru NEWS.
Josef Průša oznámil zveřejnění kompletních CAD souborů rámů tiskáren Prusa CORE One a CORE One L. Nejsou vydány pod obecnou veřejnou licenci GNU ani Creative Commons ale pod novou licencí OCL neboli Open Community License. Ta nepovoluje prodávat kompletní tiskárny či remixy založené na těchto zdrojích.
Nový CEO Mozilla Corporation Anthony Enzor-DeMeo tento týden prohlásil, že by se Firefox měl vyvinout v moderní AI prohlížeč. Po bouřlivých diskusích na redditu ujistil, že v nastavení Firefoxu bude existovat volba pro zakázání všech AI funkcí.
struct pollfd[N] a druhé pole ukazatelů na struktury, kde bude uložen pointer na callback a index, kde se fd nachází (aby odebrání bylo O(1)). Deskriptorů nebude hodně (v řádu stovek), ale budou se často měnit. Když bude jeden mít hodnotu 5, druhý 300 a třetí 60000, tak kvůli tomu nechci alokovat (dvě) pole s 60000 prvky, aby to mohlo být O(1), takže potřebuju ten index. Při odebrání prostě na místo přesunu poslední prvek. Každý thread bude mít event loop, takže by to ve výsledku bylo moc paměti. Stačí, že už kernel obsahuje mapování 1:1 na deskriptory, aby to mohlo být O(1). Takže souhrn:
typedef struct PollHandler PollHandler;
typedef void (*PollCallback)(PollHandler*, int events);
struct PollHandler
{
PollCallback callback;
};
struct MyUserStruct
{
int someMemberHere;
PollHandler pollHandler;
int moreMembersHere;
};
Uživatel předá fd, požadované události a pointer na PollHandler do funkce na začátek pollování. Pointer na PollHandler bych uložil do epoll_data (popř. ho zkombinoval s fd). Když dostanu event z epoll_wait, tak přečtu pointer na PollHandler a zavolám callback s adresou PollHandleru. Z něho si pak uživatel spočítá adresu struktury a ušetří tak jeden pointer na 'userdata'.
// Po epoll wait:
(*pollHandler->callback)(pollHandler, readyEvents);
// a v callbacku
void userCallback(PollHandler* h, int events)
{
MyUserStruct* us = (MyUserStruct)((char*)h - offsetof(MyUserStruct, pollHandler));
// dělej něco
}
Jenže chci umožnit, že v samotném callbacku může uživatel jako reakci na danou událost odstranit (či přidat) další takové 'handlery', takže nastane situace, kdy mám třeba pár set descriptorů vrácených v bufferu z epoll_wait a uživatel odebere nějaký descriptor, který může být v tomto bufferu. Musím tedy odstranit nejen decriptor z epoll deskriptoru a pak lineárně projít ten buffer a kontrolovat epoll_data, jestli tam není a pak ho buď nastavit na NULL, nebo na místo něho dát poslední položku a o jednu zmenšit počet položek. A to je to, čemu chci zabránit, procházet lineárně ten seznam, což by mohlo být pak i několikrát za sebou.
I kdybych použil další nepřímý ukazatel, kde bych měl ukazatel na uživatelův ukazatel, tak on by zase musel někam uložit tento, aby s ním pak mohl odstranit descriptor, abych ho zase já mohl uvolnit. To má za následek alokování další struktury s tím, že uživatel místo neušetří (musí si pointer schovat). Pak ještě budu muset udržovat linked list 'uvolněných' těchto bloků a až dojedu na konec bufferu, tak je uvolnit, popř. nechat pro další použití (asi lepší). ... No třeba by to nebylo špatné, ještě se nad tím zamyslím.
struct poll_handler
{
uintptr_t magic_value_1;
uintptr_t magic_value_2;
};
Kde
magic_value_1 = (((uintptr_t)fd & 0xffff0000u) << 48)
| (uintptr_t)callback
| (uintptr_t)flags;
magic_value_2 = (((uintptr_t)fd & 0xffffu) << 48)
| (uintptr_t)userdata;
nebo (podle nastavení flags)
magic_value_2 = next_poll_handler;
Tím mám 16 bytů na strukturu.
Vejdou se tam uživatelská data (musí být platný ukazatel, tj. má 47 spodních bitů (pointery s bitem 47 (který se pak kopíruje i do zbytku do 63) jsou rezervovány pro kernel), zarovnání je nedůležité, spodní bity v userdata nepoužiji. Nahoře mám 17 bitů, použiju jen 16 a tam kydnu tam spodních 16 bitů deskriptoru.
Pak callback, kompilátor funkce zarovnává na 16, a opět max je 47 bitů. Takže horních 16 bitů pro horních 16 bitů deskriptoru, spodní 4 bity na flagy. Flag zatím užiju jeden, 'removed'. Ten nastavím, když uživatel odstraní deskriptor, zároveň se přepíšou userdata na pointer na další odstraněnou položku ... jak tedy uživatel odstraňuje, dělám linked list odstraněných položek.
Obsluhování bufferu je tak, že procházím položky. Když je bit 'removed' nastaven, položku přeskočím, když ne, zavolám callback a jdu na další. Až dojedu na konec, tak struktury nalinkuju do seznamu s 'volnými' handlery. Ty neuvolňuju a nechávám je pro další použití při přidání deskriptoru.
No ... a stejně se mi to nelíbí, je to hrozná splácanina, jestli to za těch ušetřených 8 bytů, o které by struktura narostla, stojí. Ale asi by byla moc hezká:
struct poll_handler
{
poll_callback cb;
void *userdata_or_next;
int fd;
int flags;
};
Při 65k descriptorech to je půl megabajtu.
Jinak koukal jsem na zdroják kernelu a epoll uchovává přidané položky v obrovských strukturách, nalinkované v červenočerném stromu a pak ještě linkované pomocí ready-stavu a pak ještě linkované jánevímčím. Přidání/odebrání/modifikace je tedy O(log N) a stojí syscall.
Tiskni
Sdílej: