fs/char_dev.c
Source file repositories/reference/linux-study-clean/fs/char_dev.c
File Facts
- System
- Linux kernel
- Corpus path
fs/char_dev.c- Extension
.c- Size
- 17046 bytes
- Lines
- 690
- Domain
- Core OS
- Bucket
- VFS And Filesystem Core
- Inferred role
- Core OS: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/init.hlinux/fs.hlinux/kdev_t.hlinux/slab.hlinux/string.hlinux/cleanup.hlinux/major.hlinux/errno.hlinux/module.hlinux/seq_file.hlinux/kobject.hlinux/kobj_map.hlinux/cdev.hlinux/mutex.hlinux/backing-dev.hlinux/tty.hinternal.h
Detected Declarations
function major_to_indexfunction chrdev_showfunction find_dynamic_majorfunction __register_chrdev_regionfunction __unregister_chrdev_regionfunction register_chrdev_regionfunction alloc_chrdev_regionfunction __register_chrdevfunction unregister_chrdev_regionfunction __register_chrdevfunction cdev_putfunction chrdev_openfunction cd_forgetfunction cdev_purgefunction exact_lockfunction cdev_addfunction cdev_set_parentfunction cdev_device_addfunction cdev_device_delfunction cdev_unmapfunction cdev_delfunction cdev_default_releasefunction cdev_dynamic_releasefunction cdev_allocfunction cdev_initfunction chrdev_initexport register_chrdev_regionexport unregister_chrdev_regionexport alloc_chrdev_regionexport cdev_initexport cdev_allocexport cdev_delexport cdev_addexport cdev_set_parentexport cdev_device_addexport cdev_device_delexport __register_chrdevexport __unregister_chrdev
Annotated Snippet
const struct file_operations *fops)
{
struct char_device_struct *cd;
struct cdev *cdev;
int err = -ENOMEM;
cd = __register_chrdev_region(major, baseminor, count, name);
if (IS_ERR(cd))
return PTR_ERR(cd);
cdev = cdev_alloc();
if (!cdev)
goto out2;
cdev->owner = fops->owner;
cdev->ops = fops;
kobject_set_name(&cdev->kobj, "%s", name);
err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);
if (err)
goto out;
cd->cdev = cdev;
return major ? 0 : cd->major;
out:
kobject_put(&cdev->kobj);
out2:
kfree(__unregister_chrdev_region(cd->major, baseminor, count));
return err;
}
/**
* unregister_chrdev_region() - unregister a range of device numbers
* @from: the first in the range of numbers to unregister
* @count: the number of device numbers to unregister
*
* This function will unregister a range of @count device numbers,
* starting with @from. The caller should normally be the one who
* allocated those numbers in the first place...
*/
void unregister_chrdev_region(dev_t from, unsigned count)
{
dev_t to = from + count;
dev_t n, next;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
if (next > to)
next = to;
kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
}
}
/**
* __unregister_chrdev - unregister and destroy a cdev
* @major: major device number
* @baseminor: first of the range of minor numbers
* @count: the number of minor numbers this cdev is occupying
* @name: name of this range of devices
*
* Unregister and destroy the cdev occupying the region described by
* @major, @baseminor and @count. This function undoes what
* __register_chrdev() did.
*/
void __unregister_chrdev(unsigned int major, unsigned int baseminor,
unsigned int count, const char *name)
{
struct char_device_struct *cd;
cd = __unregister_chrdev_region(major, baseminor, count);
if (cd && cd->cdev)
cdev_del(cd->cdev);
kfree(cd);
}
static __cacheline_aligned_in_smp DEFINE_SPINLOCK(cdev_lock);
static struct kobject *cdev_get(struct cdev *p)
{
struct module *owner = p->owner;
struct kobject *kobj;
if (!try_module_get(owner))
return NULL;
kobj = kobject_get_unless_zero(&p->kobj);
if (!kobj)
module_put(owner);
return kobj;
}
Annotation
- Immediate include surface: `linux/init.h`, `linux/fs.h`, `linux/kdev_t.h`, `linux/slab.h`, `linux/string.h`, `linux/cleanup.h`, `linux/major.h`, `linux/errno.h`.
- Detected declarations: `function major_to_index`, `function chrdev_show`, `function find_dynamic_major`, `function __register_chrdev_region`, `function __unregister_chrdev_region`, `function register_chrdev_region`, `function alloc_chrdev_region`, `function __register_chrdev`, `function unregister_chrdev_region`, `function __register_chrdev`.
- Atlas domain: Core OS / VFS And Filesystem Core.
- Implementation status: pattern implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.