Yog*_*R.L 6 filesystems operating-system system-calls linux-device-driver linux-kernel
目前,我正在学习Linux设备驱动程序.并坚持打开设备文件的工作原理?
到目前为止我所得到的...考虑一个打开普通文件的简单代码..
#incldue<stdio.h>
int main() {
FILE fp;
char buffer[20];
fp = fopen(/home/yoggi/foo.txt, "r");
fread(buffer, 5, 1, fp);
}
Run Code Online (Sandbox Code Playgroud)
在上面的程序中,fopen(),c-library函数是系统调用open()的包装函数,该实体在VFS层函数中调用sys_open()或file_open().由于linux支持多个文件系统,因此虚拟文件系统将控件转移到实际的文件系统处理程序,以打开该文件.
1) How does virtual file system(VFS) get to know on which file system the
underline file resides?
2) How does it then calls the file_open or open function of that particular
filesystem to open file.
Run Code Online (Sandbox Code Playgroud)
如果设备驱动程序发生类似的事情.假设一个简单的设备驱动程序.
#include <linux/module.h>
// othher includes...
static dev_t first; // Global variable for the first device number
static struct cdev c_dev; // Global variable for the character device structure
static struct class *cl; // Global variable for the device class
static int my_open(struct inode *i, struct file *f)
{
printk(KERN_INFO "Driver: open()\n");
return 0;
}
static ssize_t my_read(struct file *f, char __user *buf, size_t len, loff_t *off)
{
printk(KERN_INFO "Driver: read()\n");
return 0;
}
struct file_operations pugs_fops =
{
.owner = THIS_MODULE,
.open = my_open,
.read = my_read,
};
static int __init ofcd_init(void) /* Constructor */
{
printk(KERN_INFO "Namaskar: ofcd registered");
if (alloc_chrdev_region(&first, 0, 1, "Shweta") < 0)
{
return -1;
}
if ((cl = class_create(THIS_MODULE, "chardrv")) == NULL)
{
unregister_chrdev_region(first, 1);
return -1;
}
if (device_create(cl, NULL, first, NULL, "mynull") == NULL)
{
class_destroy(cl);
unregister_chrdev_region(first, 1);
return -1;
}
cdev_init(&c_dev, &pugs_fops);
if (cdev_add(&c_dev, first, 1) == -1)
{
device_destroy(cl, first);
class_destroy(cl);
unregister_chrdev_region(first, 1);
return -1;
}
return 0;
}
static void __exit ofcd_exit(void) /* Destructor */
{
cdev_del(&c_dev);
device_destroy(cl, first);
class_destroy(cl);
unregister_chrdev_region(first, 1);
printk(KERN_INFO "Alvida: ofcd unregistered");
}
module_init(ofcd_init);
module_exit(ofcd_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anil Kumar Pugalia <email_at_sarika-pugs_dot_com>");
MODULE_DESCRIPTION("Our First Character Driver");
Run Code Online (Sandbox Code Playgroud)
首先,我们为设备分配主要次要编号.注册设备文件范围并将设备文件操作链接到设备驱动程序功能.
我没有得到的一些术语是......
1) What does actually cdev_add() do? in terms of registering a device to the
kernel.
2) Registering a device to the kernel means?
3) How does a open(/dev/mynull, O_RONLY); called on a device file actually calls
the open function of driver which is mapped while initializing the device
by calling routine cdev_init(&c_dev, &pugs_fops); ?
Run Code Online (Sandbox Code Playgroud)
saw*_*ust 10
1)虚拟文件系统(VFS)如何知道下划线文件所在的文件系统?
您必须通过其完整路径名(或当前工作目录)指定要尝试打开的文件.
因此,通过向后遍历此目录路径,到安装点的第一个匹配(最深路径)将提供已安装的文件系统,文件系统类型和设备.
每个文件系统在挂载时都会提供此信息并保存在挂载表中.
您可以使用该mount命令查看此(当前状态)信息.
2)然后如何调用该特定文件系统的file_open或open函数来打开文件.
知道文件系统后,将ops检索该fs 的结构,并open()可以调用入口点.
1)cdev_add()实际上做了什么?在将设备注册到内核方面.
驱动程序注册(例如,cdev_init()对于char设备)安装驱动程序的ops结构,该结构列出了驱动程序可以执行的功能的入口点.
cdev_add()通知内核驱动程序可以控制该char设备类型的特定实例.为该设备实例分配一个次要编号,该编号将设备名称/dev与驱动程序中的状态信息相关联.
请注意,除char之外的设备类型(例如网络或平台(总线)设备)属于不同的子系统,并使用不同的注册过程.
2)将设备注册到内核意味着什么?
现在已启用对该设备的访问权限.
3)如何打开(/ dev/mynull,O_RONLY); 在设备文件上调用实际调用驱动程序的open函数,该函数在通过调用例程cdev_init(&c_dev,&pugs_fops)初始化设备时映射; ?
init()只有在加载驱动程序时才应调用驱动程序的例程.此例程应探测设备的所有实例的存在和操作状态.应获取诸如中断线,DMA通道和I/O端口和/或存储空间之类的资源.驱动程序ops使用内核注册其结构.驱动程序使用内核注册设备的每个实例.
open()用户空间中的调用由C库处理.该/dev设备名称被转换到设备主设备号(其识别哪个设备子系统或类,例如TTY或音频,具有处理请求)和辅号码(其识别要使用的设备驱动器和该装置的实例被访问).处理器切换到管理程序模式,以便open()可以调用内核驱动程序的例程,该例程从驱动程序的ops结构中检索.有关ops结构的更多信息,请参阅其他答案.