Skip to content

Topic archive

Linux

An open-source operating system ecosystem known for its flexibility, developer tooling, and widespread use on servers, cloud platforms, embedded devices, and workstations.

115 articles
Linux 26 Sep 2026 4 min read

Batch Resize Images with Bash and ImageMagick Without Overwriting Originals

A resize command is straightforward. Keeping a batch recoverable takes more care. Writing results over the source images can leave a collection only partly processed if a conversion fails. Flattening every result into one folder also creates collisions: events/photo.jpg and products/photo.jpg would have the same destination name. A separate output tree avoids both problems. The script below accepts a source directory, a destination directory, and a maximum edge length. It processes JPEG, PNG, and WebP files recursively, retains their relative paths and formats, and leaves the originals alone.

Linux 26 Sep 2026 5 min read

Batch Convert JPEG and PNG to WebP with Bash and cwebp

Two files named photo.jpg and photo.png in the same directory would both become photo.webp. A batch converter that notices the collision only after it starts encoding may leave one image unconverted or replace an earlier result. It is better to check the entire input list first. The Bash script here uses cwebp for encoding and keeps a separate output tree. Its default auto mode encodes JPEG with lossy WebP and PNG with lossless WebP. The source images stay in place; existing destination files are skipped.

Linux 23 Sep 2026 4 min read

TFD_TIMER_CANCEL_ON_SET Turns Realtime Clock Jumps into ECANCELED

An absolute timer tied to CLOCK_REALTIME has a dependency that a monotonic deadline does not: an administrator, synchronization service, or privileged process can move the wall clock discontinuously while the timer is armed. Linux timerfd can expose that event explicitly. With TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, a qualifying clock jump causes a current or later read() on the timer descriptor to fail with ECANCELED. This behavior separates two events that would otherwise be easy to conflate: reaching a scheduled wall-clock instant and invalidating the clock basis used to schedule it.

Linux 23 Sep 2026 4 min read

signalfd Consumes Blocked Signals Through File Descriptor Reads

signalfd Consumes Blocked Signals Through File Descriptor Reads signalfd() turns selected signal notifications into records that can be consumed with read(). A matching pending signal makes the descriptor readable, which allows signal handling to share the same poll(), select(), or epoll path as sockets, timers, and other descriptors. The descriptor does not redirect signals merely because its mask names them. Normal signal-mask rules still apply. In the usual design, the selected signals are blocked before they can be delivered through their ordinary dispositions, then a signalfd reads the pending instances.

Linux 23 Sep 2026 4 min read

PR_SET_PDEATHSIG Binds a Child Notification to Parent Thread Exit

PR_SET_PDEATHSIG Binds a Child Notification to Parent Thread Exit PR_SET_PDEATHSIG lets a Linux process request a signal when the thread that created it terminates. The mechanism is narrow: it is a kernel-delivered notification tied to a parental relationship, not a general process-lifetime contract and not a guarantee that two processes terminate together. That distinction matters in supervisors, launchers, and helper processes. A child can react to loss of its creator without polling a PID, but the exact parent identity, setup timing, inheritance rules, and credential transitions define where the mechanism stops.

Linux 23 Sep 2026 4 min read

pidfd_getfd Duplicates a Target Descriptor into the Calling Process

pidfd_getfd Duplicates a Target Descriptor into the Calling Process pidfd_getfd() can place a duplicate of another process’s open file descriptor into the caller’s descriptor table. The returned descriptor is local to the caller, but it refers to the same open file description as the selected descriptor in the target process. That distinction matters. This operation does not reopen a pathname, reconstruct a socket, or create an independent file position. It duplicates an existing kernel reference across a process boundary.

Linux 23 Sep 2026 5 min read

membarrier Private Expedited Orders Userspace Memory Across Threads

Linux membarrier() can move part of a synchronization cost from a frequently executed path to a less frequent coordination path. With MEMBARRIER_CMD_PRIVATE_EXPEDITED, one thread asks the kernel to establish a memory-ordering point across the running threads in the same process. The caller pays for the system call when coordination is needed instead of requiring every fast-path execution to carry an explicit hardware memory barrier. This is narrower than a general thread rendezvous. membarrier() does not run an application callback on sibling threads, does not wait for application-level acknowledgements, and does not turn ordinary data races into valid synchronization. Its contract concerns ordering of userspace memory accesses around the barrier.

Linux 23 Sep 2026 3 min read

MADV_WIPEONFORK Replaces Inherited Private Memory with Zeroes

MADV_WIPEONFORK Replaces Inherited Private Memory with Zeroes A normal fork() gives the child mappings derived from the parent’s address space, with private writable pages commonly handled through copy-on-write. MADV_WIPEONFORK changes that inheritance rule for a selected private anonymous range: the mapping remains present in the child, but its contents are zero-filled there. The parent keeps its existing bytes. The operation therefore changes child-visible memory at the process-creation boundary rather than erasing the parent’s range.

Linux 23 Sep 2026 4 min read

MADV_DONTFORK Excludes Memory Ranges from Child Address Spaces

MADV_DONTFORK changes a specific part of Linux process creation: a mapping marked with this advice is not made available in the child created by fork(). The parent keeps the mapping. The child starts without that address range, so an address that was valid there in the parent is not automatically valid in the child. This is a semantic control over mapping inheritance, not a cache hint. It belongs to the Linux-specific madvise() operations whose effects can change memory behavior.

Linux 23 Sep 2026 5 min read

fcntl OFD Locks Follow Open File Descriptions Instead of Processes

Traditional POSIX record locks have a property that can surprise code with several descriptors for the same file: lock ownership is associated with the process, and closing a descriptor for that file can release the process’s locks on it. Linux open file description locks move ownership to the kernel open file description referenced by a descriptor. The interface still uses fcntl() and struct flock, but the ownership boundary changes. F_OFD_SETLK, F_OFD_SETLKW, and F_OFD_GETLK make byte-range locking track the open file description rather than the process identity.

Linux 23 Sep 2026 5 min read

eventfd Semaphore Mode Turns Counter Values into Single-Unit Reads

Linux eventfd exposes a kernel-maintained 64-bit counter through a file descriptor. Its compact interface hides an important semantic choice: a normal read drains the current counter value, while an EFD_SEMAPHORE read consumes exactly one unit. The write path still adds values to the same counter. That distinction changes the object from an aggregate notification counter into a descriptor-backed source of individually consumable units. The readiness model remains compatible with poll, epoll, and related descriptor multiplexing, so the same object can connect producer accounting with an event loop without adding a separate pipe payload.

Linux 23 Sep 2026 4 min read

EPOLLEXCLUSIVE Limits Wakeups Across epoll Instances

EPOLLEXCLUSIVE Limits Wakeups Across epoll Instances EPOLLEXCLUSIVE changes event distribution when several epoll instances register the same target file description. Without the flag, a readiness event can wake waiters associated with every interested epoll instance. With exclusive registrations, Linux can restrict that fan-out and reduce redundant wakeups. The flag does not make delivery single-consumer, does not assign ownership of the target, and does not replace application-level coordination. Its contract is narrower: among epoll instances that registered a target with EPOLLEXCLUSIVE, one or more receive an event for a wakeup rather than requiring all of them to receive it.

Linux 23 Sep 2026 5 min read

close_range with UNSHARE Separates File Descriptor Cleanup from Peer Threads

A multithreaded Linux process can share one file descriptor table across its threads. That arrangement is convenient during normal execution: a descriptor opened by one thread becomes available to its peers. It becomes less convenient when one thread is preparing a restricted execution context and wants to discard a broad descriptor range without racing with peers that can still allocate descriptors. close_range() provides a range operation for this boundary. With CLOSE_RANGE_UNSHARE, the kernel first separates the caller from the shared descriptor table and then applies the requested closure to the caller’s resulting table. The operation is close to combining unshare(CLONE_FILES) with a range close, but the kernel can perform less work in common cases.

Linux 22 Sep 2026 5 min read

TFD_TIMER_CANCEL_ON_SET Reports Realtime Clock Discontinuities

A timerfd armed against wall-clock time can cross a discontinuous clock adjustment before its deadline. With TFD_TIMER_CANCEL_ON_SET, Linux exposes that event through the descriptor: a subsequent read() fails with ECANCELED rather than presenting the clock jump as an ordinary timer expiration. The flag is deliberately narrow. It applies only when timerfd_settime() arms an absolute timer on CLOCK_REALTIME or CLOCK_REALTIME_ALARM, and it changes the handling of discontinuous changes to those clocks.

Linux 22 Sep 2026 5 min read

SO_PEEK_OFF Gives UNIX Sockets a Stateful Peek Cursor

SO_PEEK_OFF Gives UNIX Sockets a Stateful Peek Cursor A normal recv(..., MSG_PEEK) examines data at the front of a socket receive queue without removing it. On Linux UNIX-domain sockets, SO_PEEK_OFF can replace that repeated front-of-queue view with a cursor that advances after each peek. The cursor is socket state. Peeking moves it forward, while consuming bytes from the front of the queue moves it backward by the amount removed. That interaction lets a process inspect successive queued regions without consuming them, while keeping the peek position tied to the remaining queue.

Linux 22 Sep 2026 6 min read

signalfd Turns Blocked Signals into Readable Events

Linux signals normally interrupt a thread through asynchronous delivery. signalfd() offers a different boundary for selected signals: keep them blocked in the relevant threads, then consume pending instances by reading a file descriptor. The signal mechanism itself does not become a byte stream. The kernel still maintains signal state and normal process- or thread-directed delivery rules. signalfd adds a file-descriptor interface for accepting signals from a configured set. Blocking and the descriptor mask are separate state A signalfd has a signal-set mask that selects which signals it can accept. That mask does not block those signals for a thread. Normal use therefore pairs descriptor creation with a signal mask operation.

Linux 22 Sep 2026 5 min read

EFD_SEMAPHORE Makes eventfd Reads Consume One Counter Unit

An eventfd normally turns its entire nonzero counter into one read result and resets the counter to zero. Creating it with EFD_SEMAPHORE changes only the read side: each successful read returns the 64-bit value 1 and subtracts one from the kernel-maintained counter. That difference lets several units accumulated by writers remain separately consumable. The object is still an eventfd, with the same counter, write rules, descriptor lifetime, and readiness integration.

Linux 21 Sep 2026 5 min read

openat2 Resolve Flags Constrain Path Traversal During Lookup

A pathname passed to openat() is resolved by the kernel, but the caller has limited control over traversal through intermediate components. Linux openat2() adds a resolve field that applies constraints to the complete lookup operation. The restriction is evaluated while components are traversed, rather than by validating a pathname in userspace and opening it later. That distinction matters when path components can change concurrently. A userspace sequence that checks a path and then opens it creates separate observations of mutable filesystem state. openat2() places the selected lookup policy in the same system call that returns the file descriptor.

Linux 21 Sep 2026 6 min read

memfd File Seals Freeze Shared Memory State

A memfd_create() file starts as a mutable anonymous file. It can be resized, written, and mapped much like a regular file, while its storage remains volatile and disappears after the last reference is released. File sealing adds a different phase to that lifecycle: after data has been populated, the kernel can permanently reject selected classes of later modification. That transition is useful when one process prepares bytes and then hands the same file description to another process. The receiver can inspect the seals attached to the inode instead of relying only on a convention that the sender will stop changing the object.

Linux 21 Sep 2026 6 min read

io_uring Multishot Accept Keeps One Accept Request Active

A normal accept request has a one-to-one shape: one submitted operation eventually yields one completion. io_uring multishot accept changes that relationship. A single accept SQE can remain active across multiple incoming connections and emit a separate completion queue entry for each accepted socket. The request is persistent, but not permanent. Each CQE carries enough state for the application to tell whether the original request can produce another completion. That boundary matters because a server that treats every successful CQE as proof that accept is still armed can silently stop accepting after the multishot request terminates.

Linux 21 Sep 2026 4 min read

futex_waitv Blocks on Multiple Futex Words in One Wait

A traditional futex wait names one futex word. That maps cleanly to a mutex or condition whose blocking state is represented by one shared 32-bit value. Some synchronization designs instead need a thread to sleep until any member of several independent states changes. futex_waitv() provides that vector wait. The caller supplies an array of wait descriptors, each containing a futex address and an expected value. The kernel checks the vector and blocks only while every entry still matches its expected state.

Linux 20 Sep 2026 5 min read

pidfd_getfd Duplicates a Live File Descriptor Across Processes

A process can acquire a usable duplicate of a file descriptor that is already open in another process without asking that process to send it over a UNIX domain socket. Linux pidfd_getfd() performs that transfer through a PID file descriptor, subject to a ptrace access check. The returned descriptor is new in the caller, but the kernel object behind it is not independent. It refers to the same open file description as the target descriptor. That distinction controls offset sharing, file status flags, and operations on the underlying object.

Linux 19 Sep 2026 5 min read

userfaultfd Write Protection Turns Memory Writes into Userspace Events

A thread can reach a valid, resident page and still stop before modifying it. With Linux userfaultfd write-protect mode, a registered page can be marked so that a write generates a userfaultfd page-fault event. A userspace handler receives that event, performs its bookkeeping, removes the protection, and lets the blocked thread continue. The mechanism sits between ordinary page permissions and application-level memory accounting. The page remains part of the process address space; the kernel redirects the write fault into a file-descriptor protocol instead of forcing the application to build the same control path around mprotect() and SIGSEGV.

Linux 19 Sep 2026 5 min read

userfaultfd Moves Selected Page-Fault Resolution into User Space

A memory access normally enters the kernel page-fault path and completes without an application choosing the page contents at that instant. Linux userfaultfd changes that boundary for registered virtual address ranges: selected faults become events on a file descriptor, and a user-space manager can supply or activate the page before the faulting thread continues. The mechanism does not replace the process page tables with a user-space data structure. The kernel still owns page-table state and performs the final mapping operation. User space gains control over specific fault classes and the timing of their resolution.