UNIX源码getfs(dev)函数指针类型赋值逻辑疑问咨询
getfs(dev) Function in Early UNIX Source Code First off, let's unpack your confusion—this is a perfect example of how early pre-ANSI C played fast and loose with type rules, plus some struct context that's missing from just the function snippet you shared.
1. m_bufp Isn't Actually an int*
In the original UNIX (think Version 6) source, the struct mount definition declares m_bufp as a struct buf *, not int*. If you're seeing it labeled as int*, that's probably a quirk of how the code was transcribed, compiled, or even displayed in older tools—early C didn't enforce strict type checking like modern C does, and pointers were often treated interchangeably with integers (since they were the same size on 16/32-bit systems back then).
The struct buf is a core kernel structure that manages disk buffers, and it absolutely has a b_addr field: this points to the actual data stored in the buffer. In this case, that data is the filesystem's superblock (a struct fs).
2. Reassigning p Makes Total Sense
Let's break down that confusing line:
p = p->m_bufp->b_addr;
Here's the play-by-play:
- First,
pis a pointer to astruct mountentry (the entry for the mounted filesystem we found). p->m_bufpgives us thestruct buf *pointing to the buffer that holds the superblock for this filesystem.p->m_bufp->b_addris the memory address of the superblock itself (the actualstruct fsdata).- Early C allowed implicit conversions between different struct pointers (as long as they were the same size, which they were), so assigning this to
p(originally astruct mount *) works here. The function's goal is to return a pointer to the superblock, so this reassignment is intentional.
3. What the Function Is Actually Doing
To put it all together, getfs(dev) exists to find the superblock for a given device:
- It loops through all mounted filesystem entries (
mount[]array) to find one matching your devicedevthat has a valid buffer. - It pulls the superblock from the buffer's
b_addr. - It runs a quick sanity check (if free block/inode counts are way too high, it resets them and logs an error).
- It returns the superblock pointer, or panics if no matching filesystem is found.
4. Why the "Type Mismatch" Looks Odd Today
Modern C would scream at this code—strict type checking forbids implicit conversions between unrelated struct pointers. But in early UNIX, the kernel code was written to be efficient and concise, leveraging the fact that all pointers were the same size and the compiler would let you get away with these sorts of casts without explicit syntax.
内容的提问来源于stack exchange,提问作者b0kiii

