PHYSIO(9)

πŸ’– PHYSIO(9) β€” the Kernel Developer's Manual glow-up πŸ’–

okay bestie, sit down, hydrate, and let me tell you about physio from the Kernel Developer's Manual β€” aka the little helper that starts I/O on raw devices. she's giving backstage-pass energy for your character devices. ✨


🌸 NAME 🌸

physio β€” initiate I/O on raw devices πŸ’…


✨ SYNOPSIS ✨

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>

int
physio(struct cdev *dev, struct uio *uio, int ioflag);

no cap, that's the whole signature. three args, one int coming back at you. 🫢


πŸ¦‹ DESCRIPTION πŸ¦‹

So physio() is a helper function, right? She gets called, like, typically from your character device read() and write() routines, and her whole job is to start I/O on a user process buffer. main character behavior fr fr. πŸ‘‘

The maximum amount of data you can transfer with each call is determined by dev->si_iosize_max. That's the ceiling, bestie. Don't test it.

Then physio() takes your I/O request, converts it into a strategy() request, and hands that shiny new request over to the driver's strategy() routine for processing. it's giving "middle manager who actually does the work". 😭

Now β€” plot twist β€” since uio normally describes user space addresses, physio() has to lock those pages into memory. She does this by calling vmapbuf() for the appropriate pages. locked in. literally. πŸ”’

And here's the thing: physio() always awaits the completion of the entire requested transfer before returning, unless an error condition gets detected earlier. she does NOT do half-jobs. she waits for the whole thing. periodt. πŸ’…


πŸŽ€ a break-down of the arguments (the besties) πŸŽ€

  • dev β€” the device number identifying the device to interact with. like, which device are we pulling up on? that one. πŸ“
  • uio β€” the description of the entire transfer as requested by the user process. ⚠️ currently, the results of passing a uio structure with the uio_segflg set to anything other than UIO_USERSPACE are undefined. undefined behaviour, babe. we do not go there. πŸ’€
  • ioflag β€” the ioflag argument from the read() or write() function calling physio(). just pass it along, she knows what to do with it. πŸ¦‹

🌈 RETURN VALUES 🌈

If everything slays, physio() returns 0. βœ…

EFAULT gets returned if the address range described by uio is not accessible by the requesting process. can't reach it? can't touch it. πŸ™ˆ

physio() will also return any error resulting from calls to the device strategy routine β€” she figures that out by examining the B_ERROR buffer flag and the b_error field. detective mode. πŸ”

πŸ‘€ heads up bestie: the actual transfer size may be less than requested by uio if the device signals an β€œend of file” condition. so like, don't assume you got the whole snack. sometimes you get a bite. πŸͺ

πŸ’œ SEE ALSO πŸ’œ


⭐ HISTORY ⭐

The physio manual page is originally from NetBSD, with minor changes for applicability with FreeBSD. so she's got lore. πŸ“œβœ¨

And the physio call has been completely re-written for providing higher I/O and paging performance. glow-up of the century, honestly. πŸ”₯


and that's the whole page, bestie!! this one came from Debian, dated January 19, 2012 β€” shoutout to the archives for keeping her iconic. mwah. πŸ’‹

πŸ“¦ where this page comes from