O víkendu probíhá v Praze na Karlově náměstí 13 konference Installfest 2026. Na programu je celá řada zajímavých přednášek a workshopů. Vstup na konferenci je zcela zdarma, bez nutnosti registrace. Přednášky lze sledovat i online na YouTube.
Mozilla a společnost Mila oznámily strategické partnerství za účelem rozvoje open source a suverénní AI. Cílem je ukázat, že open source AI může konkurovat uzavřeným systémům. Obě organizace chtějí posílit technologickou suverenitu a snížit závislost na hrstce velkých technologických firem.
Adam Rice předvedl, že pomocí DNS lze distribuovat a spustit kompletní hru DOOM. Rozdělil WAD soubory a binárky do téměř 2000 DNS záznamů v Cloudflare zóně (jeden TXT záznam v DNS může nést okolo 2000 znaků textu). Ty pak stáhl PowerShellem, dekomprimoval a spustil přímo v paměti počítače bez nutnosti zápisu na disk, což prakticky dokazuje, že DNS může sloužit jako distribuované úložiště dat a možný kanál pro načítání kódu. Repozitář projektu je na GitHubu.
Dnes a zítra probíhají Arduino Days 2026. Na programu je řada zajímavých přednášek. Sledovat je lze od 17:00 na YouTube. Zúčastnit se lze i lokálních akcí. Dnes v Poličce v městské knihovně a zítra v Praze na Matfyzu.
Byla vydána beta verze Ubuntu 26.04 LTS s kódovým názvem Resolute Raccoon. Přehled novinek v poznámkách k vydání. Dle plánu by Ubuntu 26.04 LTS mělo vyjít 23. dubna 2026.
Byla vydána aktualizována Příručka pro začínající wikipedisty a wikipedistky (pdf).
Ubuntu plánuje v budoucích verzích nahradit tradiční nástroje pro synchronizaci času (chrony, linuxptp a gpsd) novým, v Rustu napsaným ntpd-rs, který nabídne vyšší bezpečnost a stabilitu.
Byla vydána nová verze 7.6 živé linuxové distribuce Tails (The Amnesic Incognito Live System), jež klade důraz na ochranu soukromí uživatelů a anonymitu. Správce hesel KeePassXC byl nahrazen správcem hesel GNOME Secrets. Bitcoinová peněženka Electrum byla povýšena na verzi 4.7.0. Tor Browser byl povýšen na verzi 15.0.8. Další novinky v příslušném seznamu.
Chris Down v obsáhlém článku „vyvrací mýty o zswap a zram“, vysvětluje, co vlastně dělají a jaké jsou mezi nimi rozdíly. Doporučuje vyhýbat se zram na serveru a bez OOM.
Porota v Los Angeles shledala firmy Google a Meta odpovědnými v přelomovém soudním sporu, který se týká závislosti na sociálních sítích; firmy musí zaplatit odškodné tři miliony dolarů (63,4 milionu Kč). Společnosti, které s verdiktem nesouhlasí, čelily obvinění, že své sociální sítě a platformy záměrně navrhly tak, aby si na nich děti vypěstovaly závislost. Porota došla k závěru, že technologické společnosti při navrhování a
… více »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: